参考【感谢大神】:
利用redis + lua解决抢红包高并发的问题_横云断岭的专栏-CSDN博客_lua redis 红包
可运行代码:里面有个redPacket的文件夹是关于抢红包的
GitHub - bailuoxi66/snapUpDemo
温馨提示:请务必仔细阅读上面的文章
1. 一种基于redis的抢红包方案
把原始的红包称为大红包,拆分后的红包称为小红包。
1.小红包预先生成,插到数据库里,红包对应的用户ID是null。生成算法见另一篇blog:http://blog.csdn.net/hengyunabc/article/details/19177877
下图举例:10元红包,分拆成了3份,分别是:3、5、2
这里之所以数据要到数据库里面:是为了数据存储,后续也为了确认哪位用户领取了多少额度的红包。
红包id 红包额度 领取红包用户 L1 3元 null L2 5元 null L3
2元 null 2.每个大红包对应两个redis队列,一个是未消费红包队列,另一个是已消费红包队列。开始时,把未抢的小红包全放到未消费红包队列里。
未消费红包队列里是json字符串,如{id:'L1', money:'3'}。
3.在redis中用一个map来过滤已抢到红包的用户。
4.抢红包时,先判断用户是否抢过红包,如果没有,则从未消费红包队列中取出一个小红包,再push到另一个已消费队列中,最后把用户ID放入去重的map中。
5.用一个单线程批量把已消费队列里的红包取出来,再批量update红包的用户ID到数据库里。
上面的流程是很清楚的,但是在第4步时,如果是用户快速点了两次,或者开了两个浏览器来抢红包,会不会有可能用户抢到了两个红包?
为了解决这个问题,采用了lua脚本方式,让第4步整个过程是原子性地执行。
2. 代码分析
1. generateTestData主要做了什么事情?
主要是:给未消费队列里面通过若干线程添加指定数量的红包【红包id和红包额度】
采用:jedis.lpush的方式
2. tryGetHongBaoScript代表的lua脚本里面的Key1和Key2分别代表什么?
结合具体的参数:
key[0]:4 没有什么意义
key[1]:未消费队列
key[2]:已消费队列
key[3]:已经抢红包的Map
key[4]:具体用户
3. 总结
这里的代码不完善,但是主要提供的一种思路。这种思路需要自身多多理解
redis运行脚本是原子性的,可以有效防止客户端调用时有不一致的问题。