秒杀大家都很熟悉,它就是在某一时刻大量请求同时抢购某一商品并完成交易的过程。作为一个支持秒杀活动的系统,面临哪些挑战,又有什么对策呢?
秒杀系统的挑战
相较于平时的售卖,秒杀最大的特点就是高并发、瞬时的高并发。由于秒杀商品的超高性价比,大量的买家涌入,给系统贡献了第一波并发用户;除此之外,还有薅羊毛党利用机器人、僵尸号等贡献的第二波并发“用户”。
这个高并发,给系统带来了一下挑战:
- 带宽耗尽
- 应用服务器负载过高最终崩溃
- 数据库压力过大崩溃
- 商品超卖
假设系统是按平时支持100并发用户设计实现的,若秒杀时有10000并发用户,系统的带宽、服务器、数据库等等是不可能抗住的。而增加100倍的带宽、服务器来支持秒杀既不经济也不现实。那么,我们如何应对呢?
秒杀系统的对策
从秒杀系统的挑战我们可以看到,一旦用户的请求都进入到后端,那么就凭平时系统的那些服务器肯本扛不住,秒杀系统会拖垮全站。该如何避免大量请求到达后端甚至拖垮全站呢?我们的基本对策应该是:
- 把尽量多的请求拦截在应用服务器之前,只放少量有效的请求进入后端,并且尽可能减少请求的数据量;
- 即使秒杀系统扛不住,也不能影响平时系统的正常运行。
对于策略1,我们可以采取的具体措施有,
- 前端页面静态化。把能静态化的元素全部静态化,减少对后端的请求。并且添加缓存,静态内容设置浏览器缓存,增加CDN缓存,使大部分请求在到达服务器之前就已经返回,减轻带宽和服务器的压力;
- 对请求限流。增加IP限流,减少一台机器上重复提交请求的次数。秒杀时用户会不断刷新/点击按钮发起请求,这时可以设置IP限流来减少。还可以增加进入秒杀页面的难度来“削峰填谷”减缓请求瞬时集中性,如设置回答问题等分散用户进入系统时间。当然更高级的还有增加风控系统来判断发起请求的账号是否为机器人/僵尸号等,若是则丢弃这些薅羊毛的账号请求。消极的限流方法还有随机丢弃一些请求,这种方法可以用在服务器接近能力上限、为避免崩溃宕机时。
- 扩容,增加前端服务器集群规模和带宽,来应对那些必不可少的请求。
- 采用内存缓存,Redis集群来替代或减少数据库操作。将秒杀系统数据提前加载至Redis集群,数据读写操作都放在Redis中,对事务性操作可以加锁。
- 使用消息队列,来更新处理后续事务,如库存更新、订单序列化等。
对于策略2,我们可以做系统隔离。秒杀系统运行在单独的服务器集群之上,不和现存生产环境共享服务器或者带宽。需要调用现有系统服务的地方有设置降级或熔断机制。
总结
本文粗略的讨论了秒杀系统的挑战以及应对策略,可以作为设计秒杀系统时的一个参考。