基于Redis实现基本抢红包算法
简介:
[key, value]的缓存数据库, Redis官方性能描述非常高, 所以面对高并发场景, 使用Redis来克服高并发压力是一个不错的手段, 本文主要基于Redis来实现基本的抢红包系统设计.
发红包模块:
1:发红包模块流程图如下:
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-03-17-22-52zWa20ymAsogokJu9.png)
用户首先输入红包金额和红包个数, 然后生成当前红包唯一标识, 并使用二倍均值算法生成随机金额的红包, 然后将生成的红包存入缓存Redis数据库中, Redis数据库中会保存当前剩余的红包数量和每个红包的金额, 由于Redis数据库是作为临时存储的地方, 所以发红包记录需要持久化存储在数据库中, 这里为加快系统响应, 使用异步的方式, 将红包金额纪录存储入Mysql数据库中, 以上就是发红包模块的简要系统设计.
2:随机生成红包金额
对于抢红包来说, 生成红包金额是非常关键的, 这里有许多生成随机数方法, 在本文中介绍一种使用较多的二倍均值算法来随机生成红包金额.对于抢红包来说, 如果发送一个金额为J的红包, 那么对与抢红包的N个人来说, 公平的概率是: 每个人抢到J / N 的金额的概率是相同的, 例如100元红包发给10个人,那么最公平的策略是使每个人抢到10元的概率相同, 二倍均值算法就是基于上面这个概率策略. 二倍均值算法流程如下: 首先设置红包金额为J, 抢红包人数为N, 接下来计算随机数区间上U = J / N * 2, 得到随机数区间(0,U), 从而在这个区间里生成第一个随机数金额M, 接下来继续生成第二个随机金额. 首先更新总红包金额为J-M,总抢红包人数为N-1, 然后生成第二个随机金额区间(0, (J-M) / (N-1) *2) , 从这个区间里面生成第二个随机金额M2, 继续迭代, 直到生成最后一个红包金额, 下图是二倍均值算法的流程
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-03-17-22-52ZuU17w7tnPGdBT52k.png)
二倍均值算法案例: 红包总金额100元, 总计10个人
计算第一个随机金额区间: 100/10X2 = 20, 第一个随机金额的区间是(0,20 ),区间均值为10
假设第一个人抢到10元,剩余金额是90 元
计算第二个随机金额区间: 90/9X2 = 20, 第一个随机金额的区间是(0,20 ),区间均值为10
假设第二个人抢到10元,剩余金额是80 元 计算第三个随机金额区间: 80/8X2 = 20, 第一个随机金额的区间是(0,20 ),区间均值为10
...............
所以使用二倍均值算法能够在不论谁先抢的情况下, 都能公平保证每个人抢到平均金额的概率是相等的, 二倍均值算法生成红包金额的代码如下:
//这里输入的totalMoney单位是分,例如100元,totalMoney = 10000
public List<Integer> getRedPackage(Integer totalMoney,Integer totalPeopleCount) {
List<Integer> moneyList = new ArrayList<>();
//暂存剩余金额为红包的总金额
Integer restMoney = totalMoney;
//暂存剩余的总人数-初始化时即为指定的总人数
Integer restPeopleCount = totalPeopleCount;
//随机数对象
Random random = new Random();
//开始循环迭代生成红包
for (int i =0;i< totalPeopleNum-1;i++){
//加1是为了至少抢到1分钱
int money = random.nextInt (restMoney / restPeopleCount * 2) + 1;
restMoney -= money;
restPeopleCount--;
moneyList.add(money);
}
//添加最后的一个红包金额