写在前面
本文一起看下Redis在秒杀场景中的应用。
1:秒杀都有哪些阶段
redis并非在秒杀的所有阶段都需要使用到,为了更好的了解redis在秒杀场景中的应用,我们先来看下秒杀的不同阶段,基本可以分为秒杀前,秒杀进行时,秒杀后。
1.1:秒杀前
秒杀前用户的动作就是在自己想要购买的页面等待倒计时,并且不断的刷新页面,等待倒计时变为购买
,此时的请求量会比较大,所以我们需要做的就是尽量将一些静态资源使用CDN缓存,比如商品的图片等,或者是客户端本地做缓存(这种可能是最优的,但是对客户端要求就增加了)
。因此,这一阶段完全使用不到Redis。
1.2:秒杀进行时
当倒计时变为可点击的购买按钮时,用户点击购买按钮,后台的逻辑如下:
1:判断库存是否充足,如果充足进入2,否则进入3
2:下单
3:提示库存不足
其中1
并发量是比较大的,因为大家同时点,对速度的要求很高,而判断库存是否充足其实就是判断库存量是否大于0,这里redis的高并发的读写特点就可以派上用场了,具体做法是使用一个哈希结构来保存总库存量,以及当前的订单量,如下:
判断过程可能如下图:
这里判断库存是否充足,以及将订单数+1的逻辑必须是原子的,不然可能出现超卖情况的发生。而想要保证原子性,可以是单命令操作,也可以使用lua脚本,这里明显只能使用lua脚本,如下:
这里的k是用户的购买数量。
判断库存充足后,接着就是下单操作了,这个下单动作是使用redis来做还是适用后端的关系型数据来做呢,答案是后端的关系型数据库,原因如下:
1:订单和后续的支付,发货等关系密切,而这些信息的关系维护都是在数据库表中的
2:订单生成的压力不大,可以在后端完成
为了增加响应用户的速度,这个生成订单的过程可以通过基于消息队列的异步方式来完成,即判断库存充足后,直接向消息队列发送一个生产订单的消息就行了,之后用户的支付,发货等过程就都可以依赖于后端服务了。
1.3:秒杀后
秒杀后,可能还有部分用户等待别人退款所以还在不断刷新页面,已下订单的用户支付超时等情况,但这些并发量都不大,也用不到redis,使用后端服务来处理就可以了,但是还是需要维护redis中的订单数量,不然就会出现数据不一致了,这个压力也不大。
2:可能有哪些问题
2.1:redis挂了怎么办?
为了保证redis的高可用,可以使用redis哨兵 来配置读写分离的集群,当主节点宕机后,自动执行主从切换,但是这有个问题需要注意,就是从节点可能是存在延迟的,即订单数量可能是实际订单数量要少的,可能出现超卖,这个时候可以从数据库中同步一次订单数量,保证订单数量的正确性。
当然还有很多其它的细节问题,需要我们在实际场景中充分考虑,尽量做到完美。