前言
最近在工作中,新接了一个红包功能的需求,这对于我来说,是非常感兴趣的,但是又有点害怕,害怕自己做不好,也没有了解过抢红包功能的实现,最后只能靠着百度,查询到了几篇非常好的文章,感谢大神的无私奉献,对我来说简直就是雪中送炭.
https://www.zybuluo.com/yulin718/note/93148
https://juejin.cn/post/6925947709517987848
需求
我这边的业务是在直播房间类发送金币红包,首先金币是没有小数点的,所以不用考虑小数点的问题,一般就是最小就发 10金币。红包类型分为 房间红包和全服红包,区别在于,房间红包只能在这个房间的人能抢,而全服红包就是所有人都能抢,红包又分为 普通红包和随机红包,普通红包就简单了,没人平均去分,随机红包就要用到微信的红包算法了 额度在0.01和剩余平均值*2之间 。
流程图
红包功能分为两种实现,一种就是预分配 红包,一种就是纯内存计算,其实这种实现都可以,在看了微信红包的架构中写到 微信金额是拆的时候实时算出来,不是预先分配的,采用的是纯内存计算,不需要预算空间存储 ,这也就表示 微信红包是纯内存计算出来的,这种情况对于机器的预算是非常吃紧的,一般来说小的公司可以忽略这些,比较流量也不大,直接就用纯内存计算就可以,预分配 : 在开奖之前就已经知道那些人能抢到红包了,或者说有抢到红包的资格,比如: 我们在看一些直播的时候,有一些抢红包操作,但是通常都会说,先买一件商品才能抢,又或者,直播发红包,要先点关注才能抢到红包,这就是预分配法,这种好处就是,能抵挡一波流量。
Redis实现
实现以上功能最简单的就是 使用 redis中的 list 结构来做了,先进行红包拆分,然后写入到 redis中,没一个人来抢的时候就pop出去,一直到没有就表示该红包被抢光了,这里建议大家看看,我发的链接上面有多红包各种实现的分析,非常好,并且也说了这种方式的弊端:抢红包时一旦从队列弹出,此时系统崩溃,恢复后此队列中的红包明细信息已丢失,需要人工补偿。 确实这就是这种实现方式最大的问题,不过,小公司也不用考虑这些,大不了就做redis的高可用。
代码实现
发红包,红包拆分:
/**
* redis list 结构实现 lpush 发红包:
* @param type 0普通红包 1.随机红包
* @param number 红包个数
* @param amount 红包金额
*/
@PostMapping("/redWars")
public void redWars(Integer type,Integer number, Integer amount){
ArrayList<Integer> arrayList = new ArrayList<>();
//总金额: 发送红包的总金币数
Integer money = number * amount;
//普通红包拆分
if(type == 0){
arrayList = commonRed(money, number);
//随机红包拆分
}else if(type == 1){
/**
* 由于我们金币是不需要小数的,我们值需要整数,所以下面代码被我改了
* 如果是金额的红包 请 参考 RoomTest
*/
arrayList = commonRoomRed(BigDecimal.valueOf(money),number);
}
//类型转换:
List<String> collect = arrayList.stream().map(i -> String.valueOf(i)).collect(Collectors.toList());
//红包key 过期时间 拆分的数据: 这就是抢红包的金额:
redisService.lpush("1002",30, TimeUnit.HOURS,collect);
}
抢红包:
/**
* list 数据接口给 lpop: 抢红包
* @param key 红包key
*/
@RequestMapping("/setLpop")
public void setLpop(String key){
String lpop = redisService.lpop(key);
if(!StringUtils.hasLength(lpop)){
System.out.println("当前红包已抢光!");
}else{
System.out.println("恭喜你抢到红包--->"+lpop);
}
}
完整代码: spring-boot-redis-integrat
实例代码在github上面需要的请自行拉取:spring-boot-integrate 然后后续会集成更多的模块进去,需要请点个star。后续会集成更多的接口实现,有需要的请保存。
如果这篇文章,有帮助到大家的,请给作者一个一键三连,谢谢