SpringBoot 结合 Redis实现抢红包功能

前言

最近在工作中,新接了一个红包功能的需求,这对于我来说,是非常感兴趣的,但是又有点害怕,害怕自己做不好,也没有了解过抢红包功能的实现,最后只能靠着百度,查询到了几篇非常好的文章,感谢大神的无私奉献,对我来说简直就是雪中送炭.

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。后续会集成更多的接口实现,有需要的请保存。
如果这篇文章,有帮助到大家的,请给作者一个一键三连,谢谢

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值