秒杀系统要点:高并发、高性能、高可用、一致性。
热点数据的处理
-
处理热点数据的问题的关键就在于我们如何找到这些热点数据(或者说热 key),然后将它们存在 jvm 内存里。对于并发量非常一般的系统直接将热点数据存放进缓存比如 Redis 中就可以了,不过像淘宝、京东这种级别的并发量,如果把某些热点数据放在 Redis 中,直接可能就将整个 Redis 集群给干掉了。
-
市面上也有一些类似的中间件,比如京东零售的 hotkey 就是一款专⻔用于检测热点数据的中间件,它可以毫秒级探测热点数据,毫秒级推送至服务器集群内存。相关阅读: 京东毫秒级热 key 探测框架设计与实践,已完美支撑 618 大促。
-
如何处理热点数据? 热点数据一定要放在缓存中,并且最好可以写入到 jvm 内存一份 (多级缓存),并设置个过期时间。需要注意写入到 jvm 的热点数据不宜过多,避免内存占用过大,一定要设置到淘汰策略。
为什么还要放在 jvm 内存一份? 因为放在 jvm 内存中的数据访问速度是最快的,不存在什么网络开销。
流量削峰
- 消息队列异步处理。
- 回答问题/验证码机制。建议除了对答案的正确性做校验,还需要对用户的提交时间做校验,比如提交时间过短(<1s)的话,大概就是使用脚本来处理的。
高可用性
集群化、限流、排队、降级、熔断。
限流的话可以直接用 Redis 来做(建议基于 Lua 脚本),也可以使用现成的流量控制组件比如 Sentinel 、Hystrix 、Resilience4J 。
Hystrix 是 Netflix 开源的熔断降级组件。
Sentinel 是阿里巴巴体提供的面向分布式服务架构的流量控制组件,经历了淘宝近 10 年双 11(11.11)购物节的所有核心场景(比如秒杀活动)的考验。Sentinel 主要以流量为切入点,提供流量控制、熔断降级、系统自适应保护等功能来保护系统的稳定性和可用性。
减库存方案
常⻅的减库存方案有:
-
下单即减库存 :只要用户下单了,即使不付款,我们就扣库存。
-
付款再减库存 :当用户付款了之后,我们在减库存。不过,这种情况可能会造成用户下订单成功,但是付款失败。
一般情况下都是下单减扣库存,像现在的购物网站比如京东都是这样来做的。
不过,我们还会对业务逻辑做进一步优化,比如说对超过一定时间不付款的订单特殊处理,释放库存。
接口幂等
如果没有做幂等性,那么一个人同时点击来多次秒杀按钮,后端会处理多次相同订单请求,导致秒杀了多个商品。
保证分布式接口的幂等性对于数据的一致性至关重要,特别是像支付这种涉及到钱的接口。保证幂等性这个操作并不是说前端做了就可以的,后端同样要做。
前端保证幂等性的话比较简单,一般通过当用户提交请求后将按钮致灰来做到。后端保证幂等性就稍微麻烦一点,方法也是有很多种,比如:同步锁、分布式锁、业务唯一索引约束等等。