99国产精品欲av蜜臀,可以直接免费观看的AV网站,gogogo高清免费完整版,啊灬啊灬啊灬免费毛片

網(wǎng)易首頁 > 網(wǎng)易號(hào) > 正文 申請(qǐng)入駐

Spring Boot + Redis:模擬 10w 人的秒殺搶單!

0
分享至

作者 | 神牛003

來源 | www.cnblogs.com/wangrudong003/p/10627539.html

本篇內(nèi)容主要講解的是redis分布式鎖,這個(gè)在各大廠面試幾乎都是必備的,下面結(jié)合模擬搶單的場(chǎng)景來使用她;本篇不涉及到的redis環(huán)境搭建,快速搭建個(gè)人測(cè)試環(huán)境,這里建議使用docker;本篇內(nèi)容節(jié)點(diǎn)如下:

Jedis的nx生成鎖

  • 如何刪除鎖

  • 模擬搶單動(dòng)作(10w個(gè)人開搶)

  • jedis的nx生成鎖

對(duì)于java中想操作redis,好的方式是使用jedis,首先pom中引入依賴:


redis.clientsgroupId>
jedisartifactId>
dependency>

對(duì)于分布式鎖的生成通常需要注意如下幾個(gè)方面:

創(chuàng)建鎖的策略:redis的普通key一般都允許覆蓋,A用戶set某個(gè)key后,B在set相同的key時(shí)同樣能成功,如果是鎖場(chǎng)景,那就無法知道到底是哪個(gè)用戶set成功的;這里jedis的setnx方式為我們解決了這個(gè)問題,簡(jiǎn)單原理是:當(dāng)A用戶先set成功了,那B用戶set的時(shí)候就返回失敗,滿足了某個(gè)時(shí)間點(diǎn)只允許一個(gè)用戶拿到鎖。

鎖過期時(shí)間:某個(gè)搶購場(chǎng)景時(shí)候,如果沒有過期的概念,當(dāng)A用戶生成了鎖,但是后面的流程被阻塞了一直無法釋放鎖,那其他用戶此時(shí)獲取鎖就會(huì)一直失敗,無法完成搶購的活動(dòng);當(dāng)然正常情況一般都不會(huì)阻塞,A用戶流程會(huì)正常釋放鎖;過期時(shí)間只是為了更有保障。

下面來上段setnx操作的代碼:

public boolean setnx(String key, String val) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return false;
return jedis.set(key, val, "NX", "PX", 1000 * 60).
equalsIgnoreCase("ok");
} catch (Exception ex) {
} finally {
if (jedis != null) {
jedis.close();

return false;

這里注意點(diǎn)在于jedis的set方法,其參數(shù)的說明如:

  • NX:是否存在key,存在就不set成功

  • PX:key過期時(shí)間單位設(shè)置為毫秒(EX:?jiǎn)挝幻耄?/p>

如果您正在學(xué)習(xí)Spring Cloud,推薦一個(gè)連載多年還在繼續(xù)更新的免費(fèi)教程:https://blog.didispace.com/spring-cloud-learning/

setnx如果失敗直接封裝返回false即可,下面我們通過一個(gè)get方式的api來調(diào)用下這個(gè)setnx方法:


@GetMapping("/setnx/{key}/{val}")
public boolean setnx(@PathVariable String key, @PathVariable String val) {
return jedisCom.setnx(key, val);

訪問如下測(cè)試url,正常來說第一次返回了true,第二次返回了false,由于第二次請(qǐng)求的時(shí)候redis的key已存在,所以無法set成功


由上圖能夠看到只有一次set成功,并key具有一個(gè)有效時(shí)間,此時(shí)已到達(dá)了分布式鎖的條件。

如何刪除鎖

上面是創(chuàng)建鎖,同樣的具有有效時(shí)間,但是我們不能完全依賴這個(gè)有效時(shí)間,場(chǎng)景如:有效時(shí)間設(shè)置1分鐘,本身用戶A獲取鎖后,沒遇到什么特殊情況正常生成了搶購訂單后,此時(shí)其他用戶應(yīng)該能正常下單了才對(duì),但是由于有個(gè)1分鐘后鎖才能自動(dòng)釋放,那其他用戶在這1分鐘無法正常下單(因?yàn)殒i還是A用戶的),因此我們需要A用戶操作完后,主動(dòng)去解鎖:

public int delnx(String key, String val) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return 0;

//if redis.call('get','orderkey')=='1111' then return redis.call('del','orderkey') else return 0 end
StringBuilder sbScript = new StringBuilder();
sbScript.append("if redis.call('get','").append(key).append("')").append("=='").append(val).append("'").
append(" then ").
append(" return redis.call('del','").append(key).append("')").
append(" else ").
append(" return 0").
append(" end");

return Integer.valueOf(jedis.eval(sbScript.toString()).toString());
} catch (Exception ex) {
} finally {
if (jedis != null) {
jedis.close();
}
}
return 0;
}

這里也使用了jedis方式,直接執(zhí)行l(wèi)ua腳本:根據(jù)val判斷其是否存在,如果存在就del;

其實(shí)個(gè)人認(rèn)為通過jedis的get方式獲取val后,然后再比較value是否是當(dāng)前持有鎖的用戶,如果是那最后再刪除,效果其實(shí)相當(dāng);只不過直接通過eval執(zhí)行腳本,這樣避免多一次操作了redis而已,縮短了原子操作的間隔。(如有不同見解請(qǐng)留言探討);同樣這里創(chuàng)建個(gè)get方式的api來測(cè)試:

@GetMapping("/delnx/{key}/{val}")
public int delnx(@PathVariable String key, @PathVariable String val) {
return jedisCom.delnx(key, val);

注意的是delnx時(shí),需要傳遞創(chuàng)建鎖時(shí)的value,因?yàn)橥ㄟ^et的value與delnx的value來判斷是否是持有鎖的操作請(qǐng)求,只有value一樣才允許del;

模擬搶單動(dòng)作(10w個(gè)人開搶)

有了上面對(duì)分布式鎖的粗略基礎(chǔ),我們模擬下10w人搶單的場(chǎng)景,其實(shí)就是一個(gè)并發(fā)操作請(qǐng)求而已,由于環(huán)境有限,只能如此測(cè)試;如下初始化10w個(gè)用戶,并初始化庫存,商品等信息,如下代碼:

//總庫存
private long nKuCuen = 0;
//商品key名字
private String shangpingKey = "computer_key";
//獲取鎖的超時(shí)時(shí)間 秒
private int timeout = 30 * 1000;

@GetMapping("/qiangdan")
public List qiangdan() {

//搶到商品的用戶
List shopUsers = new ArrayList<>();

//構(gòu)造很多用戶
List users = new ArrayList<>();
IntStream.range(0, 100000).parallel().forEach(b -> {
users.add("神牛-" + b);
});

//初始化庫存
nKuCuen = 10;

//模擬開搶
users.parallelStream().forEach(b -> {
String shopUser = qiang(b);
if (!StringUtils.isEmpty(shopUser)) {
shopUsers.add(shopUser);
}
});

return shopUsers;
}

有了上面10w個(gè)不同用戶,我們?cè)O(shè)定商品只有10個(gè)庫存,然后通過并行流的方式來模擬搶購,如下?lián)屬彽膶?shí)現(xiàn):


* 模擬搶單動(dòng)作
* @param b
* @return
private String qiang(String b) {
//用戶開搶時(shí)間
long startTime = System.currentTimeMillis();

//未搶到的情況下,30秒內(nèi)繼續(xù)獲取鎖
while ((startTime + timeout) >= System.currentTimeMillis()) {
//商品是否剩余
if (nKuCuen <= 0) {
break;
}
if (jedisCom.setnx(shangpingKey, b)) {
//用戶b拿到鎖
logger.info("用戶{}拿到鎖...", b);
try {
//商品是否剩余
if (nKuCuen <= 0) {
break;
}

//模擬生成訂單耗時(shí)操作,方便查看:神牛-50 多次獲取鎖記錄
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}

//搶購成功,商品遞減,記錄用戶
nKuCuen -= 1;

//搶單成功跳出
logger.info("用戶{}搶單成功跳出...所剩庫存:{}", b, nKuCuen);

return b + "搶單成功,所剩庫存:" + nKuCuen;
} finally {
logger.info("用戶{}釋放鎖...", b);
//釋放鎖
jedisCom.delnx(shangpingKey, b);
}
} else {
//用戶b沒拿到鎖,在超時(shí)范圍內(nèi)繼續(xù)請(qǐng)求鎖,不需要處理
// if (b.equals("神牛-50") || b.equals("神牛-69")) {
// logger.info("用戶{}等待獲取鎖...", b);
// }
}
}
return "";
}

另外,如果您正在學(xué)習(xí)Spring Cloud,推薦一個(gè)連載多年還在繼續(xù)更新的免費(fèi)教程:https://blog.didispace.com/spring-cloud-learning/

這里實(shí)現(xiàn)的邏輯是:

1、parallelStream():并行流模擬多用戶搶購

2、(startTime + timeout) >= System.currentTimeMillis():判斷未搶成功的用戶,timeout秒內(nèi)繼續(xù)獲取鎖

3、獲取鎖前和后都判斷庫存是否還足夠

4、jedisCom.setnx(shangpingKey, b):用戶獲取搶購鎖

5、獲取鎖后并下單成功,最后釋放鎖:jedisCom.delnx(shangpingKey, b)

再來看下記錄的日志結(jié)果:


最終返回?fù)屬彸晒Φ挠脩簦?/p>

END

2021年Java原創(chuàng)面試題庫連載中

更多內(nèi)容,點(diǎn)擊上方名片查看

特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相關(guān)推薦
熱點(diǎn)推薦
75歲港星宣布征婚,自曝37歲兒子內(nèi)地求學(xué)失敗,回家躺平需要他養(yǎng)

75歲港星宣布征婚,自曝37歲兒子內(nèi)地求學(xué)失敗,回家躺平需要他養(yǎng)

探源歷史
2025-07-21 07:29:49
港媒爆料趙雅芝日子挺苦的,被3個(gè)兒子長(zhǎng)期啃老,71歲還不能老!

港媒爆料趙雅芝日子挺苦的,被3個(gè)兒子長(zhǎng)期啃老,71歲還不能老!

木子愛娛樂大號(hào)
2025-07-05 09:37:33
又現(xiàn)跨省聯(lián)動(dòng):汕尾市長(zhǎng)調(diào)往揚(yáng)州,揚(yáng)州市長(zhǎng)調(diào)往寧德

又現(xiàn)跨省聯(lián)動(dòng):汕尾市長(zhǎng)調(diào)往揚(yáng)州,揚(yáng)州市長(zhǎng)調(diào)往寧德

觀察者網(wǎng)
2025-07-23 14:39:26
新華社快訊:“十四五”期間,全國(guó)公安機(jī)關(guān)共破獲電信網(wǎng)絡(luò)詐騙案件173.9萬起

新華社快訊:“十四五”期間,全國(guó)公安機(jī)關(guān)共破獲電信網(wǎng)絡(luò)詐騙案件173.9萬起

新華社
2025-07-23 15:27:09
杭州偷水男“社會(huì)性死亡”:正臉曝光,工作毀了,連公司都被牽連

杭州偷水男“社會(huì)性死亡”:正臉曝光,工作毀了,連公司都被牽連

嘆知
2025-07-22 15:45:43
汪峰組織兩家人日本度假,森林北9歲女兒首曝光,長(zhǎng)得比醒醒漂亮

汪峰組織兩家人日本度假,森林北9歲女兒首曝光,長(zhǎng)得比醒醒漂亮

瓜農(nóng)娟姐
2025-07-23 18:29:01
公職人員下班后兼職送三小時(shí)外賣:“像打游戲做任務(wù)”一樣快樂|封面頭條

公職人員下班后兼職送三小時(shí)外賣:“像打游戲做任務(wù)”一樣快樂|封面頭條

封面新聞
2025-07-22 15:48:22
或許遺憾才是人生的常態(tài):C羅本不會(huì)離開皇馬,更不應(yīng)在尤文虛度

或許遺憾才是人生的常態(tài):C羅本不會(huì)離開皇馬,更不應(yīng)在尤文虛度

K唐伯虎
2025-07-21 07:19:39
470000人集體大逃亡!以色列萬萬沒想到歷史會(huì)又一次倒置重演

470000人集體大逃亡!以色列萬萬沒想到歷史會(huì)又一次倒置重演

南方健哥
2025-07-23 18:37:44
山西、陜西兩地2025年養(yǎng)老金調(diào)整都漲2%嗎?養(yǎng)老金4000元漲80元?

山西、陜西兩地2025年養(yǎng)老金調(diào)整都漲2%嗎?養(yǎng)老金4000元漲80元?

文雅筆墨
2025-07-23 17:09:26
酷玩樂隊(duì)演唱會(huì)“出軌”的女方:來自百億老錢家族,捐贈(zèng)大樓給哈佛大學(xué)

酷玩樂隊(duì)演唱會(huì)“出軌”的女方:來自百億老錢家族,捐贈(zèng)大樓給哈佛大學(xué)

封面新聞
2025-07-22 19:48:45
重慶雙胞胎兄弟分別被清華、北大錄取

重慶雙胞胎兄弟分別被清華、北大錄取

封面新聞
2025-07-23 14:55:04
“絕經(jīng)和出道同時(shí)來?”上海街頭驚現(xiàn)她的巨幅海報(bào)!網(wǎng)友:笑著笑著就哭了

“絕經(jīng)和出道同時(shí)來?”上海街頭驚現(xiàn)她的巨幅海報(bào)!網(wǎng)友:笑著笑著就哭了

環(huán)球網(wǎng)資訊
2025-07-23 10:48:19
遂寧市紀(jì)委回應(yīng)“公職人員兼職送外賣”:已了解該情況

遂寧市紀(jì)委回應(yīng)“公職人員兼職送外賣”:已了解該情況

極目新聞
2025-07-23 11:17:30
郭麒麟,正式開除德云社。

郭麒麟,正式開除德云社。

會(huì)說話的舌
2025-07-18 13:40:49
一聲巨響!俄羅斯轟炸波蘭企業(yè),波蘭頭上懸了3年的劍終于落地了

一聲巨響!俄羅斯轟炸波蘭企業(yè),波蘭頭上懸了3年的劍終于落地了

文雅筆墨
2025-07-21 09:10:43
大火燒毀獲賠償,重建2000平洛杉磯豪宅,易建聯(lián)要花多少錢?

大火燒毀獲賠償,重建2000平洛杉磯豪宅,易建聯(lián)要花多少錢?

東球弟
2025-07-23 14:12:13
小姑子在嫂子訂婚宴上搶走三金,果斷退婚:不敢嫁“強(qiáng)盜”

小姑子在嫂子訂婚宴上搶走三金,果斷退婚:不敢嫁“強(qiáng)盜”

惟來
2025-07-22 18:20:02
足協(xié)杯-申花vs河南首發(fā):4外援PK5外援 吳曦、蔣圣龍、王上源先發(fā)

足協(xié)杯-申花vs河南首發(fā):4外援PK5外援 吳曦、蔣圣龍、王上源先發(fā)

直播吧
2025-07-23 17:36:13
三伏天是男人進(jìn)補(bǔ)的黃金期,多吃3道“扶陽菜”,精力充沛身體壯

三伏天是男人進(jìn)補(bǔ)的黃金期,多吃3道“扶陽菜”,精力充沛身體壯

鬼菜生活
2025-07-23 17:38:39
2025-07-23 20:07:00
Meta
Meta
關(guān)注java進(jìn)階架構(gòu)師送架構(gòu)
1059文章數(shù) 9856關(guān)注度
往期回顧 全部

科技要聞

別自嗨了!XREAL徐馳:AI眼鏡只有5歲智商

頭條要聞

印度、孟加拉關(guān)切雅魯藏布江下游水電站工程 中方回應(yīng)

頭條要聞

印度、孟加拉關(guān)切雅魯藏布江下游水電站工程 中方回應(yīng)

體育要聞

英格蘭最紅球星 也是加勒比島國(guó)驕傲

娛樂要聞

汪峰森林北同游日本 各帶各娃互不耽誤

財(cái)經(jīng)要聞

律師解析娃哈哈遺產(chǎn)案:遺囑是最大變數(shù)

汽車要聞

德系大招放盡 場(chǎng)地極限測(cè)試全新奧迪A5L

態(tài)度原創(chuàng)

時(shí)尚
藝術(shù)
本地
數(shù)碼
公開課

看來看去還是這些穿搭適合普通人!配色不艷、衣服不花,好得體

藝術(shù)要聞

故宮珍藏的墨跡《十七帖》,比拓本更精良,這才是地道的魏晉寫法

本地新聞

這雙丑鞋“泰”辣眼,跪求內(nèi)娛不要抄作業(yè)

數(shù)碼要聞

全漢帶來 VIC GD 系列電源:僅擁有 3 年質(zhì)保的金牌非模組 ATX

公開課

李玫瑾:為什么性格比能力更重要?

無障礙瀏覽 進(jìn)入關(guān)懷版 主站蜘蛛池模板: 闻喜县| 留坝县| 阳原县| 突泉县| 肇东市| 玉溪市| 高邮市| 门源| 千阳县| 湖州市| 三亚市| 怀集县| 陆河县| 汾西县| 临海市| 黎城县| 淳化县| 宁海县| 阳春市| 巴彦淖尔市| 潞西市| 来宾市| 新昌县| 内江市| 平邑县| 宜春市| 婺源县| 望都县| 信丰县| 土默特左旗| 固始县| 伊金霍洛旗| 罗平县| 墨脱县| 梅州市| 延津县| 贵定县| 福贡县| 颍上县| 青岛市| 贺兰县|