redis设计秒杀活动图解

版权声明:原创文章,未经允许不得转载. https://blog.csdn.net/shengqianfeng/article/details/86656143

最近找时间浏览了网上的一些文章,结合自己的思考,觉得需要出一个秒杀活动的技术方案。大家可以参考,也可以指正,这里都表示热烈欢迎!技术只有相互探讨才能碰撞出智慧的火花,问题也就随之清晰明朗。闲话不多扯了,先上一副流程图,描述下大概秒杀流程。

场景:公司周年之际,准备答谢客户,于是想策划一起秒杀活动,一共有100件商品,且要求每个用户只能抢一件商品,并且用户抢到后如果30分钟内没有付款,则取消订单,释放库存给其他用户抢。

在这里插入图片描述
我们来一步一步分析下:
首先第一个问题:如何解决用户抢购过了,不准再抢这个问题?
分析:用户抢购商品后会携带一个userId发起抢购请求,我们该如何避免用户刷单呢?这里我们在请购请求到达后,首先将用户放进一个hash集合中,可以采用redis的Hash来存放:

Long first = jedis.hset("userQueue", "0000000001", "0000000001");

对于userQueue这个key的hash结构来说,userId是其field,userId也是其value,第一次放入0000000001这个用户返回值为1,第二次放入则返回值是0,且redis是单线程顺序执行命令,所以一定只能放进去一个0000000001用户,这样就控制住同一个用户只能进入userQueue队列1次,同一个用户可以提示“已经参与抢购!”,那进入队列后这个用户要干什么呢?
当然是抢购了,在这里有一个很关键的问题要注意:商品一共100件,最终抢到商品的也只能是userQueue中的100个用户,如何保证第101个用户买不到商品?现在的设计是将库存100先放进一个redis的list结构中,来一个用户pop一个,直到最后pop出第100个秒杀结束。提示“抢光了!”pop成功则进入下单流程,插入新订单到数据库,初始状态0未支付(0:未支付 1:已支付,2:30min已过期)。对于过期的则归还库存到redis的库存list中等待pop。

期初的设计是这样的如下图(略复杂):
将用户的的请求preOderpush放进redis的list列表中,key为一个应用中定义的AutomicInteger值,value为用户ID即userId,但是考虑到分布式应用场景(毕竟我们的秒杀服务端可能不止一台机器)key可能需要做分布式计数,那么我想到的就是ZK实现的分布式计数器
DistributedAtomicInteger,入队后+1,订单过期未支付-1,入队后获取+1后的值是否超过100,如果超过则提示抢购结束,否则抢到商品且入队成功。
存放进抢购队列的preOder将会被我们事先定义的定时任务TASK1扫描,这个定时任务的逻辑就是将抢购队列的preOder预订单生在DB订单表中成正式订单,并且初始状态为0:未支付
0:未支付 1:已支付,2:30min已过期)。
我们用TASK2来扫描数据库中超过30分钟未支付的过期订单,更新状态为2:已过期。同时分布式计数器-1.此时可以进来一个新的抢购用户!
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/shengqianfeng/article/details/86656143