写在前面

本文一起看下Redis在秒杀场景中的应用。

redis实现秒杀步骤 redis如何实现秒杀_redis实现秒杀步骤

1:秒杀都有哪些阶段

redis并非在秒杀的所有阶段都需要使用到,为了更好的了解redis在秒杀场景中的应用,我们先来看下秒杀的不同阶段,基本可以分为秒杀前,秒杀进行时,秒杀后。

1.1:秒杀前

秒杀前用户的动作就是在自己想要购买的页面等待倒计时,并且不断的刷新页面,等待倒计时变为购买,此时的请求量会比较大,所以我们需要做的就是尽量将一些静态资源使用CDN缓存,比如商品的图片等,或者是客户端本地做缓存(这种可能是最优的,但是对客户端要求就增加了)。因此,这一阶段完全使用不到Redis。

1.2:秒杀进行时

当倒计时变为可点击的购买按钮时,用户点击购买按钮,后台的逻辑如下:

判断库存是否充足,如果充足进入2,否则进入3

2:下单

3:提示库存不足

其中1并发量是比较大的,因为大家同时点,对速度的要求很高,用户对时延非常敏感,而判断库存是否充足其实就是判断库存量是否大于0,这里redis的高并发的读写特点就可以派上用场了,具体做法是使用一个哈希结构来保存总库存量,以及当前的订单量,如下:

redis实现秒杀步骤 redis如何实现秒杀_redis实现秒杀步骤_02

判断过程可能如下图:

redis实现秒杀步骤 redis如何实现秒杀_redis_03

这里判断库存是否充足,以及将订单数+1的逻辑必须是原子的,不然可能出现超卖情况的发生。而想要保证原子性,可以是单命令操作,也可以使用lua脚本,这里明显只能使用lua脚本,如下:

redis实现秒杀步骤 redis如何实现秒杀_redis实现秒杀步骤_04

这里的k是用户的购买数量。

判断库存充足后,接着就是下单操作了,这个下单动作是使用redis来做还是适用后端的关系型数据来做呢,答案是后端的关系型数据库,原因如下:

1:订单和后续的支付,发货等关系密切,而这些信息的关系维护都是在数据库表中的

2:订单生成的压力不大,可以在后端完成

3:用户对时延不敏感

为了增加响应用户的速度(有库存,且库存扣减成功,则代表用户具备了购买商品的资格,订单可后续生成),这个生成订单的过程可以通过基于消息队列的异步方式来完成,即判断库存充足后,直接向消息队列发送一个生产订单的消息就行了,之后用户的支付,发货等过程就都可以依赖于后端服务了。

1.3:秒杀后

秒杀后,可能还有部分用户等待别人退款所以还在不断刷新页面,已下订单的用户支付超时等情况,但这些并发量都不大,也用不到redis,使用后端服务来处理就可以了,但是还是需要维护redis中的订单数量,不然就会出现数据不一致了,这个压力也不大。

2:可能有哪些问题

2.1:redis挂了怎么办?

为了保证redis的高可用,可以使用redis哨兵 来配置读写分离的集群,当主节点宕机后,自动执行主从切换,但是这有个问题需要注意,就是从节点可能是存在延迟的,即订单数量可能是实际订单数量要少的,可能出现超卖,这个时候可以从数据库中同步一次订单数量,保证订单数量的正确性。

当然还有很多其它的细节问题,需要我们在实际场景中充分考虑,尽量做到完美。

写在后面

小结

秒杀其实就只需要解决判断当前库存是否满足客户订单量就行了,因为该过程用户会同时点击,并发量最大,因此该过程需要用到Redis,剩余的下单,发货等流程,压力都不会很大,直接使用关系型数据库就行了。