秒杀程序架构演进

最近的项目上,有秒杀的需求,我负责技术验证和可行性研究。技术选型比较明确,SpringBoot+MySQL+Redis,基本上做秒杀都是这么个选型。秒杀主要是两个诉求,快还要准。不能慢,慢了是小时杀不是秒杀。不准,那就是浪费成本了。

靠程序加锁和MySQL的事务可以实现,但是太慢,无法支撑秒杀业务的需求。如果前置部署一套Redis,通过DECR指令来判断,由于事务隔离的问题并不能保证不出现超卖,只是由于Redis的性能很好出现的少一些。实测20并发5000请求大致出现4-6次超卖,已经很高了。

由于秒杀程序可售出的货物量是一定的,那么可以将这部分商品预热到Redis中,使用List存放。秒杀开始之前LPUSH进去,秒杀开始后RPOP取数。如果还有剩余,RPOP可以取到结果。如果没有库存,Redis取到的是nil,认为无库存。对于每天准点补充库存的情况,可以使用定时任务进行PUSH操作。

Redis里队列的PUSH和POP操作都是O(1)的复杂度,性能很好。此处不需要使用LLEN判断是否有剩余,POP取数成功即为库存。虽然LLEN也是常量级,但是毕竟是操作,能免则免。同理,不需要设置一个变量来表示某商品是否可以秒杀,直接POP即可。

此处如果需要记录日志,可以将日志PUSH到队列中,程序里使用fixedRate定时调度,持久化到MySQL。基本结构如下图所示。

 

 

posted @ 2020-10-30 15:46  徐浩然  阅读(103)  评论(0编辑  收藏  举报