拆红包的核心功能:

拆红包功能是整个功能的核心,红包计算逻辑:剩余金额/剩余红包个数 * 2,这里有个一个点,如果保证剩余金额和剩余红包个数同时等于0,特别是在并发的情况下。

核心代码:

public RetDTO<?> getRedPacketMoney(int uid, long redPacketId){//这里判断用户是否已经抢过红包了,以及是否还有红包可以抢Map map = this.getRedPacket(redPacketId, uid);int code = CommonUtil.getRedPacketStatus(map);if(code == 100){return new RetDTO<String>(StatusCode.IS_EXISTS.getCode(),StatusCode.IS_EXISTS.getMsg(),null);}if(code < 100){return new RetDTO<String>(StatusCode.IS_QIANG.getCode(),StatusCode.IS_QIANG.getMsg(),null);}if(code > 100){String redPacketName = redPacketId + TOTAL_NUM;String totalAmountName = redPacketId + TOTAL_AMOUNT;//剩下的次数String num = (String)redisService.get(redPacketName);Integer totalNumInt = Integer.parseInt(num);if (StringUtils.isBlank(num) || Integer.parseInt(num) == 0) {return new RetDTO<String>(StatusCode.ISOVER.getCode(),StatusCode.ISOVER.getMsg(),null);}//剩下的金额String totalAmount = (String) redisService.get(totalAmountName);if (StringUtils.isNotBlank(totalAmount)){//获取随机金额Integer totalAmountInt = Integer.valueOf(totalAmount);Integer randomAmount = CommonUtil.getMaxMoney(totalAmountInt,totalNumInt);if(randomAmount != null && randomAmount > 0){//用来记录谁已经领过红包了String userReceive = redPacketName + "_" + uid;//从安全性上考虑===============这块的代码可以考虑分布式事务,保证数据一致性===============================//lua脚本里面完成了多个命令校验  lua脚本的传参:总金额key,红包总数key,本次红包金额,用户key//excretepacket.lua 1.需要进行剩余金额和红包个数的校验,如果没有剩余金额,则不可再抢红包,如果没有红包个数也不能再抢红包//2.另外特别需要说明的,当最后一个红包的时候,本次红包金额,不能再用,直接把剩下的金额给最后一个用户(这里坑了我大半天,在并发的情况下一直没办法保证总金额和红包个数的数据匹配)String result = redisService.getRedPacketMoney("excretepacket.lua", totalAmountName,redPacketName,String.valueOf(randomAmount),userReceive);//这里lua脚本会放用户抢到的金额,如果返回非金额,则请不要执行落库操作if(CommonUtil.isNumeric(result)){//目前压测发现这里是性能的瓶颈 ,可以考虑利用MQ的形式进行落库updateRacketInDB(uid, redPacketId,Integer.valueOf(result));return new RetDTO<>(StatusCode.ISSUCCESS.getCode(),StatusCode.ISSUCCESS.getMsg(),"恭喜您抢到了"+ randomAmount);}//==================================================================================================}else {return new RetDTO<>(StatusCode.IS_ERROR.getCode(),StatusCode.IS_ERROR.getMsg(),"见鬼了");}}}return new RetDTO<String>(StatusCode.IS_ERROR.getCode(),StatusCode.IS_ERROR.getMsg(),null);}

lua脚本

local totalAmountName = KEYS[1]
local redPacketName = KEYS[2]
local randomAmount = KEYS[3]
local userReceive = KEYS[4]local result_1 = redis.call("GET",totalAmountName)
local result_2 = redis.call("GET",redPacketName)local result = "ABC"if tonumber(result_1) >= tonumber(randomAmount) thenif tonumber(result_2) > 0 thenif tonumber(result_2) == 1 thenredis.call("DECRBY",totalAmountName,result_1)redis.call("DECR", redPacketName)redis.call("SET", userReceive,userReceive)return result_1elseredis.call("DECRBY", totalAmountName, randomAmount)redis.call("DECR", redPacketName)redis.call("SET", userReceive,userReceive)return randomAmountendend
elsereturn result
end

说明:本功能是基于springBoot2.0开发,设计到技术及插件,springBoot2.0,swagger,mybaits,redis,lua脚本,mysql,都是一些常用的功能。

Redis应用项目---抢红包功能(四)相关推荐

  1. Redis应用项目---抢红包功能(一)

    开篇: 之前也看过一些相关的书籍,最近又在学习redis的相关知识,不过这次偏实战一些,花了几天时间做了一个抢红包的功能,把设计的思路以及最终的源码贴出来给大家分享一下,本人自己自测了一下,能非常清楚 ...

  2. Redis应用项目---抢红包功能(三)

    抢红包逻辑及核心代码: 先判断用户有没有抢过红包,如果没有则进行第二步 判断红包个数,如果>0 则直接返回数量 判断红包金额,如果>0则直接返回金额 核心代码 说明:这里特别需要说明的,r ...

  3. Redis应用项目---抢红包功能(二)

    发红包逻辑及核心代码: 需要保证红包id的唯一性,此次用的是雪花算法,完全能够保证唯一性,关于分布式事务的唯一性ID,可以给大家推进一篇我写的博客,里面有多种唯一性ID的介绍:https://blog ...

  4. 基于Redis实现微信抢红包功能

    使用Redis和Lua的原子性实现抢红包功能 安装Lua(可选) 编写lua脚本 lua脚本学习可以参考 [https://www.runoob.com/lua/lua-basic-syntax.ht ...

  5. 基于redis实现抢红包功能(包括余额退回处理)

    本文将讲述使用redis实现抢红包功能,采用发红包时将红包拆好存储,解决红包金额平衡问题(两种算法).解决超发现象.将数据通过消息队列传递给另一个服务写入数据库,现阶段不考虑redis宕机的情况. - ...

  6. Redis 牛X!竟然能实现抢红包功能!

    原文链接:https://www.cnblogs.com/chenyanbin/p/13587508.html 为啥写这个微信抢红包项目呢,公司 0202 年 08 月 22 日,公司周年庆,抢了10 ...

  7. Redis在项目中的地位及使用场景剖析

    Redis在项目中的地位及使用场景剖析 一. redis 特点 所有数据存储在内存中,高速读写 提供丰富多样的数据类型:string. hash. set. sorted set.bitmap.hyp ...

  8. Redis在项目中的使用及性能测试

    强烈推荐一个大神的人工智能的教程:http://www.captainbed.net/zhanghan [前言] 在上篇博文中为大家分享了<SCPPO:C#中Redis封装的类>,有了这个 ...

  9. SSM+bootstrap4+mysql+redis原创项目实战:搭建校园二手交易网

    项目已部署到阿里云:hbxytrade.top 本文更新时间:2020/3/7,更新内容:redis缓存中间件(涉及多条件查询).物品管理界面(更新.上架.下架等操作).阿里云部署项目 代码地址: h ...

最新文章

  1. 问题引发由于与GI相关的python脚本中的错误,Gnome终端无法启动
  2. FMS3系列(六):使用远程共享对象(SharedObject)实现多人时时在线聊天(Flex | Flash)
  3. Codeforces Round #624 (Div. 3) E. Construct the Binary Tree 思维 + 构造
  4. 剑指 Offer 38. 字符串的排列(有重复元素的排列)
  5. Linux下抓包工具tcpdump以及分析包的工具wireshark
  6. 使用该JavaBean可以将数据在JSP页面中以表格的形式显示出来 并具有动态排序 动态生成查询 自动分页功能
  7. ASP.NET Core 系列视频完结,新项目实战课程发布。
  8. Java代码怎么取消订阅功能,RxJava2 中多种取消订阅 dispose 的方法梳理( 源码分析 )...
  9. python如何运用ols_python - 如何在python中使用OLSResults.f_test与实验组进行测试 - SO中文参考 - www.soinside.com...
  10. 努力做一个优秀的programmer [ C# 影院售票系统]
  11. 迅为IMX6ULL开发板Linux系统移植-NXP官方Linux源码编译
  12. 找工作笔试面试那些事儿(14)---轻松一下,谈谈面试注意的点
  13. 小鸡腿U T7 NEERC2011
  14. js实现身份证号码验证
  15. Blender几何节点新手教学
  16. 爱普生墨仓式打印机故障检查,卡纸,清洗打印头,补充墨水详解(非常实用)
  17. 电脑声卡驱动正常但是没有声音怎么办 电脑声卡坏了怎么办
  18. 电子科技大学计算机与科学学院,电子科技大学计算机科学与工程学院(网络空间安全学院)、资源与环境学院赴我所调研考察...
  19. 看看您电脑里哪些端口会被入侵?
  20. CAD自学不要怕,这里有你需要的CAD制图初学入门教程!

热门文章

  1. boss直聘改回系统头像_Boss直聘VS猎聘,谁的营销广告更胜一筹
  2. 大学计算机实验教程实验6,《大学计算机基础实验教程》参考答案.(6页)-原创力文档...
  3. 100BASE-T1 /1000BASE-T1 车载以太网转换器产品汇总
  4. vue3.0网易云音乐及入门小案例
  5. HTML5中利用JavaScript实现拖放(来回)的案例
  6. linux ln命令详解
  7. linux5关闭apic服务,阐述Linux内核里面的APIC编程
  8. 3月18日作业-监理师培训
  9. Django站内消息通知
  10. leetcode 1217. Play with Chips 解法 python