一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|數(shù)據(jù)庫技術(shù)|

服務(wù)器之家 - 數(shù)據(jù)庫 - Redis - 通過redis的腳本lua如何實現(xiàn)搶紅包功能

通過redis的腳本lua如何實現(xiàn)搶紅包功能

2020-07-05 17:00yuansmlk Redis

這篇文章主要給大家介紹了關(guān)于通過redis的腳本lua如何實現(xiàn)搶紅包功能的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

redis 腳本介紹

Redis從2.6版本開始,通過內(nèi)嵌支持Lua環(huán)境

好處

  • 減少網(wǎng)絡(luò)開銷。可以將多個請求通過腳本的形式一次發(fā)送,減少網(wǎng)絡(luò)延遲
  • 原子操作。redis將整個腳本當(dāng)作一個整體去執(zhí)行,中間不會被其他命令插入,無需擔(dān)心腳本執(zhí)行過程中會出現(xiàn)競態(tài)條件
  • 復(fù)用。客戶端發(fā)送的腳本會永久保存在redis中,可以復(fù)用這一腳本

數(shù)據(jù)庫表設(shè)計

簡單兩張表,一個紅包表,一個紅包領(lǐng)取記錄表

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 '數(shù)量(分割成幾分)',
 `create_time` datetime DEFAULT NULL COMMENT '創(chuàng)建時間',
 `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 '領(lǐng)取到獎勵',
 `red_envelope_id` bigint(20) DEFAULT NULL COMMENT '紅包id',
 `create_time` datetime DEFAULT NULL COMMENT '創(chuàng)建時間',
 `update_time` datetime DEFAULT NULL COMMENT '更新時間',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COMMENT='紅包領(lǐng)取記錄'

代碼編寫

首先,生成一個紅包,將其分成指定數(shù)量的隨機小紅包,以list結(jié)構(gòu)(envelope:redEnvelopeId:紅包id作為key)存儲在reids中(以便搶紅包彈出數(shù)據(jù))

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public Long divideRedEnvelope(int amount, int num) {
 /**
  * 每個人至少分到一分錢,如果有2000分,6人,隨機得到五個小于1994(2000-6)的數(shù)
  * 比如 a1=4,a2=120,a3=324,a4=500,a5=700(隨機拿到的五個數(shù)進(jìn)行排序),那么紅包錢分別為: 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;
 /**
  * 隨機數(shù)
  */
 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;
  }
 }
 /**
  * 產(chǎn)生的小紅包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();
}

搶紅包時,根據(jù)用戶userId和紅包id,生成KEYS[1]、KEYS[2]、KEYS[3] (存儲小紅包的key、領(lǐng)取紅包記錄的key、用戶userId的key)傳入腳本中。

?     1、先判斷該用戶是否搶過紅包,有則返回-1,沒有則從紅包列表取出一個小紅包

?     2、步驟1的小紅包如果為空,則表明紅包已經(jīng)沒搶光,返回 -2

?     3、否則返回取出的小紅包金額

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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();
 /**
  * 產(chǎn)生的小紅包key
  */
 keyList.add("envelope:redEnvelopeId:" + redEnvelopeId);
 /**
  * 紅包領(lǐng)取記錄key
  */
 keyList.add("envelope:record:" + redEnvelopeId);
 keyList.add("" + userId);
 keyList.add(String.valueOf(userId));
 /**
  * -1 已經(jīng)搶到紅包 -2 紅包已經(jīng)完了 ,其余是搶到紅包并返回紅包余額
  */
 String result = stringRedisTemplate.execute(redisScript, keyList);
 return result;
}

實現(xiàn)搶紅包的Lua腳本

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class LuaScript {
 
 /**
  * -1 已經(jīng)搶到紅包 -2 紅包被搶光 re 紅包金額 ,keys[1]、keys[2]、keys[3]分別為存儲小紅包的key、紅包領(lǐng)取記錄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數(shù)據(jù)庫和redis

通過redis的腳本lua如何實現(xiàn)搶紅包功能

通過redis的腳本lua如何實現(xiàn)搶紅包功能

通過redis的腳本lua如何實現(xiàn)搶紅包功能

通過jmeter進(jìn)行壓測搶紅包

通過redis的腳本lua如何實現(xiàn)搶紅包功能

結(jié)果

通過redis的腳本lua如何實現(xiàn)搶紅包功能

通過redis的腳本lua如何實現(xiàn)搶紅包功能

github代碼鏈接

鏈接

總結(jié)

到此這篇關(guān)于通過redis的腳本lua如何實現(xiàn)搶紅包功能的文章就介紹到這了,更多相關(guān)redis的腳本lua實現(xiàn)搶紅包內(nèi)容請搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文鏈接:https://juejin.im/post/5ebeab656fb9a0433567b36f

延伸 · 閱讀

精彩推薦
  • RedisRedis的配置、啟動、操作和關(guān)閉方法

    Redis的配置、啟動、操作和關(guān)閉方法

    今天小編就為大家分享一篇Redis的配置、啟動、操作和關(guān)閉方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧 ...

    大道化簡5312019-11-14
  • Redisredis中如何使用lua腳本讓你的靈活性提高5個逼格詳解

    redis中如何使用lua腳本讓你的靈活性提高5個逼格詳解

    這篇文章主要給大家介紹了關(guān)于redis中如何使用lua腳本讓你的靈活性提高5個逼格的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具...

    一線碼農(nóng)5812019-11-18
  • RedisRedis如何實現(xiàn)數(shù)據(jù)庫讀寫分離詳解

    Redis如何實現(xiàn)數(shù)據(jù)庫讀寫分離詳解

    Redis的主從架構(gòu),能幫助我們實現(xiàn)讀多,寫少的情況,下面這篇文章主要給大家介紹了關(guān)于Redis如何實現(xiàn)數(shù)據(jù)庫讀寫分離的相關(guān)資料,文中通過示例代碼介紹...

    羅兵漂流記6092019-11-11
  • RedisRedis全量復(fù)制與部分復(fù)制示例詳解

    Redis全量復(fù)制與部分復(fù)制示例詳解

    這篇文章主要給大家介紹了關(guān)于Redis全量復(fù)制與部分復(fù)制的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Redis爬蟲具有一定的參考學(xué)習(xí)...

    豆子先生5052019-11-27
  • Redisredis實現(xiàn)排行榜功能

    redis實現(xiàn)排行榜功能

    排行榜在很多地方都能使用到,redis的zset可以很方便地用來實現(xiàn)排行榜功能,本文就來簡單的介紹一下如何使用,具有一定的參考價值,感興趣的小伙伴們...

    乘月歸5022021-08-05
  • Redisredis 交集、并集、差集的具體使用

    redis 交集、并集、差集的具體使用

    這篇文章主要介紹了redis 交集、并集、差集的具體使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友...

    xiaojin21cen10152021-07-27
  • RedisRedis 事務(wù)知識點相關(guān)總結(jié)

    Redis 事務(wù)知識點相關(guān)總結(jié)

    這篇文章主要介紹了Redis 事務(wù)相關(guān)總結(jié),幫助大家更好的理解和學(xué)習(xí)使用Redis,感興趣的朋友可以了解下...

    AsiaYe8232021-07-28
  • Redis詳解Redis復(fù)制原理

    詳解Redis復(fù)制原理

    與大多數(shù)db一樣,Redis也提供了復(fù)制機制,以滿足故障恢復(fù)和負(fù)載均衡等需求。復(fù)制也是Redis高可用的基礎(chǔ),哨兵和集群都是建立在復(fù)制基礎(chǔ)上實現(xiàn)高可用的...

    李留廣10222021-08-09
主站蜘蛛池模板: 91进入蜜桃臀在线播放 | 91麻豆制片厂 | 国产欧美va欧美va香蕉在线观看 | 色久久一个亚洲综合网 | 亚洲国产精品一区二区三区久久 | 操操小说 | 亚洲欧美日韩综合一区久久 | 日本在线观看视频 | 五月色婷婷在线影院 | 成人免费毛片一区二区三区 | free性泰国女人hd | 久久草香蕉频线观 | 好爽好紧小雪别夹小说 | 性白俄罗斯高清xxxxx | 精品成人网 | 经典WC女厕所里TV | 日本大片在线 | 国产精品一区牛牛影视 | 天天干天天日天天射天天操毛片 | 国产裸舞在线一区二区 | 日本高免费观看在线播放 | 亚洲国产果果在线播放在线 | 亚洲大尺码| 九九精品免视看国产成人 | 成年男女免费视频网站 | 天天做天天玩天天爽天天 | 农夫69小说小雨与农村老太 | 欧美日一级片 | 麻豆最新 | 高h细节肉爽文办公室 | 91搞搞| 17岁韩国在线观看免费1 | 嫩模被黑人粗大挺进 | 99热这里只有精品在线 | 色噜噜视频影院 | 99久热只有精品视频免费看 | 亚洲AVAV天堂AV在线网爱情 | 欧美一级片免费 | 美女被吸乳得到大胸 | mm131亚洲精品久久 | yy8090韩国日本三理论免费 |