通过redis的脚本lua如何实现抢红包功能
数据库表设计
简单两张表,一个红包表,一个红包领取记录表
CREATE TABLE `t_red_envelope` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT ID ,
`amount` decimal(10,2) DEFAULT NULL COMMENT 金额 ,
`num` int(11) DEFAULT NULL COMMENT 数量(分割成几分) ,
`create_time` datetime DEFAULT NULL COMMENT 创建时间 ,
`update_time` datetime DEFAULT NULL COMMENT 更新时间 ,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COMMENT= 红包
CREATE TABLE `t_red_envelope_record` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT id ,
`user_id` bigint(20) DEFAULT NULL COMMENT 用户id ,
`reward` decimal(10,2) DEFAULT NULL COMMENT 领取到奖励 ,
`red_envelope_id` bigint(20) DEFAULT NULL COMMENT 红包id ,
`create_time` datetime DEFAULT NULL COMMENT 创建时间 ,
`update_time` datetime DEFAULT NULL COMMENT 更新时间 ,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COMMENT= 红包领取记录
代码编写
首先,生成一个红包,将其分成指定数量的随机小红包,以list结构(envelope:redEnvelopeId:红包id作为key)存储在reids中(以便抢红包弹出数据)
public Long divideRedEnvelope(int amount, int num) { * 每个人至少分到一分钱,如果有2000分,6人,随机得到五个小于1994(2000-6)的数 * 比如 a1=4,a2=120,a3=324,a4=500,a5=700(随机拿到的五个数进行排序),那么红包钱分别为: a1+1,a2-a1+1,a3-a2+1,a4-a3+1,a5-a4+1,1994-a5+1(总和刚好为2000) RedEnvelope redEnvelope = new RedEnvelope(); redEnvelope.setAmount(new BigDecimal(amount)); redEnvelope.setNum(num); redEnvelope.setCreateTime(new Date()); redEnvelope.setUpdateTime(new Date()); redEnvelopeDao.insert(redEnvelope); * 拿来随机分的,按分来算 int totalAmount = amount * 100 - num; * 随机数 int[] randomNum = new int[num - 1]; * 红包金额 int[] redEnvelopeAmount = new int[num]; for (int i = 0; i num - 1; i++) { int rand = new Random().nextInt(totalAmount); randomNum[i] = rand; Arrays.sort(randomNum); * 条件语句分别分配的第一个、最后一个、中间的红包 for (int i = 0; i num; i++) { if (i == 0) { redEnvelopeAmount[i] = randomNum[i] + 1; } else if (i == num - 1) { redEnvelopeAmount[i] = totalAmount - randomNum[i - 1] + 1; } else { redEnvelopeAmount[i] = randomNum[i] - randomNum[i - 1] + 1; * 产生的小红包key,以list存储在reids中 String key = "envelope:redEnvelopeId:" + redEnvelope.getId(); Boolean flag = stringRedisTemplate.hasKey(key); if (!flag) { for (Integer i : redEnvelopeAmount) { stringRedisTemplate.opsForList().leftPush(key, i + ""); return redEnvelope.getId(); }
抢红包时,根据用户userId和红包id,生成KEYS[1]、KEYS[2]、KEYS[3] (存储小红包的key、领取红包记录的key、用户userId的key)传入脚本中。
1、先判断该用户是否抢过红包,有则返回-1,没有则从红包列表取出一个小红包
2、步骤1的小红包如果为空,则表明红包已经没抢光,返回 -2
3、否则返回取出的小红包金额
public String grabRedEnvelope(Long userId, Long redEnvelopeId) { DefaultRedisScript String redisScript = new DefaultRedisScript (); redisScript.setResultType(String.class); redisScript.setScriptText(LuaScript.redLua); List String keyList = new ArrayList(); * 产生的小红包key keyList.add("envelope:redEnvelopeId:" + redEnvelopeId); * 红包领取记录key keyList.add("envelope:record:" + redEnvelopeId); keyList.add("" + userId); keyList.add(String.valueOf(userId)); * -1 已经抢到红包 -2 红包已经完了 ,其余是抢到红包并返回红包余额 String result = stringRedisTemplate.execute(redisScript, keyList); return result; }
实现抢红包的Lua脚本
public class LuaScript { * -1 已经抢到红包 -2 红包被抢光 re 红包金额 ,keys[1]、keys[2]、keys[3]分别为存储小红包的key、红包领取记录key、用户id public static String redLua = "if redis.call("hexists",KEYS[2],KEYS[3]) ~=0 then \n" + " return "-1";\n" + " else \n" + "local re=redis.call("rpop",KEYS[1]);\n" + "if re then\n" + "redis.call("hset",KEYS[2],KEYS[3],1);\n" + "return re;\n" + "else\n" + "return "-2";\n" + "end\n" + "end"; }
测试
首先通过接口分配红包生成一个100块、份额为10份的红包,并将其mysql数据库和redis
通过jmeter进行压测抢红包
结果
github代码链接
链接
到此这篇关于通过redis的脚本lua如何实现抢红包功能的文章就介绍到这了,更多相关redis的脚本lua实现抢红包内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
我想要获取技术服务或软件
服务范围:MySQL、ORACLE、SQLSERVER、MongoDB、PostgreSQL 、程序问题
服务方式:远程服务、电话支持、现场服务,沟通指定方式服务
技术标签:数据恢复、安装配置、数据迁移、集群容灾、异常处理、其它问题
本站部分文章参考或来源于网络,如有侵权请联系站长。
数据库远程运维 通过redis的脚本lua如何实现抢红包功能
相关文章
- 深入剖析Redis:让你更理解它(redis的理解)
- 文件分布式存储Redis实现PDF文件的分布式存储(redis实现pdf)
- 深入浅出:理解Redis的实现原理(redis的实现原理)
- 实现分布式环境中基于Redis的手写锁(手写redis分布式锁)
- 艾编程用Redis解锁新技术时代(艾编程redis)
- 不甘心秒杀Redis挂了,如何继续(秒杀redis挂了怎么办)
- 用Redis缓存加快数据访问速度(用redis缓存什么数据)
- 最新Redis下载体验新一代的强大性能(最新redis下载)
- 断开Redis连接了无痕迹(关闭与redis的链接)
- Redis数据更新技巧实现提升(如何更新redis数据)
- 锁实现Redis分布式锁的步骤分析(如何做redis 分布式)
- 启动Redis验证 验证密码的正确性(启动验证redis密码)
- 数据Redis集群中如何安全删除数据(redis 集群上 删除)
- 解决Redis键值对过期调用方法(redis 过期调用方法)
- Redis改变转发量的强大力量(redis 转发量)
- 缓存实现快速响应Redis请求级别缓存(redis 请求级别)
- 让Redis视频更出彩如何正确设置(redis视频设置)
- Redis实现轻松的持久层(redis落持久层)
- 用Redis实现多种分类信息检索(redis获取分类可以)
- 配置Redis主从机器,搭建高可用集群(redis配置主从机器)
- 快速理解Redis连接池使用方法(redis连接池怎么使用)
- 校验尽显效能利用Redis实现输入校验(redis输入)
- Redis读音学习英式发音(redis读音发音英语)