秒杀系统总结

来源:互联网 发布:菜鸟商城android源码 编辑:程序博客网 时间:2024/06/10 06:03

挑战与解决策略

压力挑战:    短暂的高流量,对现有网站业务造成冲击         秒杀是一个网站营销的一个附加活动,时间短,并发量大。         如果和网站原有应用部署在一起,必然会对现有业务造成冲击,稍有不慎可能导致整个网站瘫痪。    高并发,数据库高负载         用户秒杀开始前,通过不断刷新浏览器来保证不会错过秒杀活动。         频繁的访问程序、数据库会对应用服务器和数据库服务器造成负载压力    网络及服务器带宽增长压力,网络带宽的问题比超过平时好多倍         如果秒杀页面的大小为200K,如果最大并发数为10000次,那么需要的网络和服务器带宽是2G(200K×10000)。         这些网络带宽是因为秒杀活动新增的,超过网站平时使用的带宽    业务逻辑的简化    避免直接下单         秒杀的游戏规则是到了秒杀才能开始对商品下单购买,在此时间点之前,只能浏览信息不可下单。         而下单页面也是一个普通的URL,如果得到这个URL,不用等到秒杀开始就可以下单了解决策略:    1.公平保证:         秒杀用户筛选策略:一般是先到先得,10个商品放100个人进来         防秒杀器和机器人:验证码等手段    2.系统压力:         秒杀系统独立部署,避免对主站造成压力和堵死                如果需要还可以使用独立域名,使其与网站完全隔离,即使秒杀系统崩溃了,也不会对网站造成影响         秒杀商品页面静态化和缓存化,减少后端请求                将商品描述、参数、详情,全部写到一个静态页面,不用进行程序的逻辑处理,不需访问数据库,不用部署动态的服务器和数据库服务器         租借秒杀活动网络带宽                为了减轻服务器的压力,需要将秒杀商品页面缓存在CDN,同样CDN服务器也需要临时租借带宽         动态生成随机下单页面的URL                为了避免用户直接访问下单URL,需要将URL动态化,用随机数作为参数,只能秒杀开始的时候才生成       关键点           业务拆分,独立并发访问           高并发控制,请求量拦截。           读写分离(查询库存和下订单拆分独立)           请求队列控制接受数,从而控制并发量           订单和支付的一致性    3.系统层级的划分:     前端 -> web层 -> 业务服务 -> DB持久层            前端                   A:扩容,加机器,这是最简单的方法,通过增加前端池的整体承载量来抗峰值。                   B:静态化,将活动页面上的所有可以静态的元素全部静态化,并尽量减少动态元素。通过CDN来抗峰值。                   C:限流一般都会采用IP级别的限流,即针对某一个IP,限制单位时间内发起请求数量。            web层                  A:   集群负载均衡,节点能线性扩展。                  B:采用短连接,连接池。            业务服务                      A:查询模块(查询库存)并发查询,库存数存在缓存中,(商品信息和图片信息等等)静态化处理和库存剩余数量缓存化处理。                      B: 下订单模块(秒杀关键部分),队列控制异步化处理,首先判断这个队列是否已满, 如果没满就将请求放入队列中排队,队列满以后的所有请求直接返回秒杀失败。                      C: 支付模块,异步付款,等待付款成功结果。(付款成功更新库存,也可下单的时候扣库存)。            DB持久层            A: 各个系统的业务数据分库存储,主从读写分离,单个子系统的数据,可以通过分库/分表的方法。            B: 构建合理数据库索引,如对购买记录添加唯一索引,数据更新检测库存,如update number set x=x-1 where (x -1 ) >= 0。    4.监控系统          A: 操作系统的cpu, memory,i/o 。          B: 各个系统的log:访问次数,warning, error log的条数。          C: dba对数据库的监控。          D: 业务层面的监控:每分钟各个子系统的交易量(DB查询)。          E: 核心路径监控,非常重要的部分,单笔请求在交易系统中的流程,一笔实时交易,从接收到http请求,到各个子系统之间的互相访问,到DB的读写,到返回抢购结果


具体架构

架构设计

  • 如何控制秒杀商品页面抢购按钮的可用/禁用。

购买按钮只有在秒杀开始的时候才能点亮,在此之前是灰色的,显示活动未开始。

如果页面是动态生成的,每次刷新都要请求服务器,那么势必造成服务端的负载压力。

如果页面是静态页面的话,可以将页面缓存在CDN,反向代理服务器上,甚至用户浏览器上。

但是这样,秒杀开始时,用户刷新页面,根本请求不到应用服务器。

解决方案:

使用JS脚本控制,在页面中引用一个JS文件(文件极小),但是该文件不要被缓存。

该JS的作用是,包含秒杀开始标志,修改样式,生成下单页面的URL及随机参数。

该JS文件不被缓存的做法:xxx.js?v=随机数。

会有一台服务器进行监控(定时上下架):

当秒杀活动开始时推送该文件。

当秒杀活动结束时推送文件,标示结束标志,修改样式。

如下图。



  • 如何只允许,第一个提交的单进入订单系统。

由于秒杀到商品的用户只有一个,因此需要在提交订单时,进行下单前置检查。

如果已经有订单提交成功,表示活动结束,进入秒杀结束页面。

事实上,订单数只能有一个,为了减轻下单页面服务器的负载压力,可以控制进入下单页面的入口。

只有少数用户能进入下单页面,其他用户直接进入秒杀结束页面。

(前置检查逻辑)检查本机已处理的下单请求数目:

如果超过10条,直接返回已结束页面给用户。

如果未超过10条,则用户可进入填写订单及确认页面。

(前置检查逻辑)检查全局已提交订单数目:

已超过秒杀商品总数,返回秒杀结束页面。

未超过秒杀商品总数,提交到子订单系统。

如下图。


  • 减库存的操作

拍下减库存(用户体验好)

付款减库存


下订单尽可能简单,购买数据为1且不可编辑,送货地址和付款方式为空或用户默认,允许订单提交后修改。



参考:

http://blog.csdn.net/yd201430320529/article/category/6861843

https://my.oschina.net/xianggao/blog/524943

https://my.oschina.net/xianggao/blog/528800


https://my.oschina.net/xianggao/blog?sort=time&p=2&temp=1505111426645



eg:例子

参考:http://www.jianshu.com/p/ac2b24e471cf?utm_campaign=hugo&utm_medium=reader_share&utm_content=note

hi,rudy,我们这一次要做个活动,大家一起来抢100张1000元现金券。你看看怎么做?现在预约人数大概在2w人左右。我擦,秒杀啊,这个得想想如何利用自己现有资源来完成瞬间的高并发处理。

他山之石

  • 徐汉彬:Web系统大规模并发——电商秒杀与抢购:http://www.csdn.net/article/2014-11-28/2822858
  • 秒杀系统架构分析与实战:http://www.cnblogs.com/andy-zhou/p/5364136.html
  • 小米网抢购系统开发实践:http://www.csdn.net/article/2014-11-07/2822545
  • 如何设计一个秒杀系统:http://www.jb51.net/article/108564.htm

秒杀的特点

  • 对现有网站业务造成冲击
  • 瞬间的高并发,但秒杀商品数量有限。真正有效请求有限。而且一般是热点数据比较多。
  • 网络及服务器带宽增长压力。
  • 业务逻辑的简化

原则

  • 不能超卖,高并发下的数据的强一致性
  • 公平性
  • 可扩展性:可以通过增加服务数量,来抗住更大的并发
  • 分流:基于时间分片削峰

解决方式

  • 公平性:

    • 防刷机制-限制n秒内,用户访问次数、
    • 验证码
    • 倒计时前后端时间同步
    • 僵尸账号防刷-在业务侧做实名制
  • 隔离:

    • 业务隔离:秒杀系统,属于短时间高并发处理,防止影响其他正常业务,应该需要独立部署
    • 动静隔离:秒杀页面尽可能减少对后台依赖,绝大部分走CDN,只有少量动态数据请求服务器
  • 网络及服务器带宽增长压力:

    • 尽可能越在靠近用户侧拦截越多无效请求越好。
    • 减少冗余数据的返回
  • 保证秒杀接口快:

    • 秒杀接口足够简化
    • 复杂逻辑异步处理
    • 尽可能越在靠近用户侧拦截越多无效请求越好。
    • 读走缓存
  • 数据一致性:

    • 将大量无效请求拦截在数据层之前,有效请求(少量)通过redis/db等中间数据层保证数据一致性
  • 可扩展性:

    • 多级缓存:各个层级,尽可能多的做缓存,以拦截无效请求。

方案一

秒杀系统设计-方案一.png
秒杀系统设计-方案一.png
  • 优点与说明:

    • 实现相对简单,能做一部分秒杀活动。
    • 前端静态资源走CDN
    • 前端做秒杀前后拦截,秒杀中,每个用户只放一次请求到后端。可以拦截掉小白用户的99%的无效点击。
    • 利用redis的(setnx、incrby/decrby等原子操作)、mysql的(for update 写锁)实现秒杀库存控制
  • 缺点:

    • 比较倚重redis
    • 过滤用户秒杀条件成为瓶颈
    • 业务耦合还是比较严重

方案二

秒杀系统设计-方案二.png
秒杀系统设计-方案二.png
  • 优点与说明:

    • 增加单机本地缓存,可以支持机器平行扩容,抗住更多请求
    • 增加mq,做异步处理,解耦复杂的业务逻辑
  • 缺点:

    • 没有机器人爬取。多个商品秒杀咋办?
    • 有没有什么降级处理?
    • 数据层还是单点


作者:林湾村龙猫
链接:http://www.jianshu.com/p/ac2b24e471cf
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

原创粉丝点击