• 秒杀/抢购系统设计优化


    12306抢票,票是有限的,库存一份,瞬时流量非常多,都读相同的库存,读写冲突,锁非常严重;
    小米手机每周二的秒杀,可能手机只有1万部,但瞬时进入的流量可能是几百几千万;
    这是秒杀业务难的地方。那我们怎么优化秒杀系统呢?

    一、难点

    (1)高并发
    用户在秒杀开始前,通过不停刷新浏览器页面以保证不会错过秒杀,这些请求如果按照一般的网站应用架构,访问应用服务器、连接数据库,会对应用服务器和数据库服务器造成负载压力。
    (2)超卖
    由于库存并发更新的问题,导致在实际库存已经不足的情况下,库存依然在减,导致卖家的商品卖得件数超过秒杀的预期。

    二、架构

    常见的站点架构基本是这样的:
    (1)浏览器端,最上层,会执行到一些JS代码
    (2)站点层,这一层会访问后端数据,拼HTML页面返回给浏览器
    (3)服务层,向上游屏蔽底层数据细节,提供数据访问
    (4)数据层,最终的库存是存在这里的

    三、思路

    (1)将请求尽量拦截在上游:传统秒杀系统之所以挂,请求都压倒了后端数据层,数据库读写锁冲突严重,导致响应慢,下单基本不能成功
    (2)利用缓存:这是一个典型的读多写少的应用场景,非常适合使用缓存

    四、解决方案

    (1)浏览器层请求拦截
    1.产品层面,用户点击“查询”或“购票”后,按钮置灰,禁止用户重复提交请求
    2.js层面,限制用户在n秒之内只能提交一次请求
    (2)站点层请求拦截与页面缓存
    1.静态化,将活动页面上的所有可以静态的元素全部静态化,并尽量减少动态元素
    2.限频率,同一个UID,限制访问频率,做页面缓存,n秒内到达站点层的请求,均返回同一页面
    (3)服务层请求拦截与数据缓存
    1.对于写请求,将所有写请求在缓存(Redis或Memcached)中,做请求单队列排队,每次只透过有限的写请求异步写入到数据层,如果均成功再放下一批,如果库存不够则队列里的写请求全部返回“已售完”
    2.对于读请求,用Redis或Memcached
    缓存写性能和读性能都远高于MySQL,只有非常少的写和读缓存的请求会透到数据层去
    (4)数据层
    1.尝试扣减库存,扣减库存成功才会进行下单逻辑(由于MySQL事务的特性,不可能完全避免超卖)

    UPDATE table_name SET n=n-1 WHERE n>1;

    2.扣减库存后进行检查,保证减完不能等于负数
    查看更多:
    开发一个微信小程序实例教程
    HTTP协议整理
    PHP安全之Web攻击
    MySQL优化
    Linux下常见的IO模型
    参考资料:
    https://my.oschina.net/xianggao/blog/524943
    http://www.infoq.com/cn/articles/flash-deal-architecture-optimization

  • 相关阅读:
    android 自定义动画4 RotateAnimation源码分析
    Android 绘图 阴影制作(Shadow)
    view, surfaceView, invalidate, postInvalidate, 刷新屏幕
    android database 常用字段描述
    Android标题栏进度指示器使用
    ThumbnailUtils Android2.2新增类
    Android 重力感应 测试代码
    Android中内嵌字体实现个性化
    Android中悬浮窗口
    Android布局Java代码构造法
  • 原文地址:https://www.cnblogs.com/quanzhiguo/p/7156715.html
Copyright © 2020-2023  润新知