SpringBoot + Redis:模擬 10w 人的秒殺搶單
往期熱門文章:
1、別瞎寫工具類了,Spring自帶的挺香的! 2、一口氣說出 Redis 16 個常見使用場景 3、監(jiān)控員工離職傾向系統(tǒng)已被下架,網(wǎng)友:勸你善良 4、同事說,我寫Java代碼像寫詩 5、阿里p7和副處級干部選哪個? 來源:www.cnblogs.com/wangrudong003/p/10627539.html
Jedis的nx生成鎖
如何刪除鎖 模擬搶單動作(10w個人開搶) jedis的nx生成鎖
????redis.clients
????jedis
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;
????}
NX:是否存在key,存在就不set成功 PX:key過期時間單位設(shè)置為毫秒(EX:單位秒)
@GetMapping("/setnx/{key}/{val}")
public?boolean?setnx(@PathVariable?String?key,?@PathVariable?String?val)?{
?????return?jedisCom.setnx(key,?val);
}

如何刪除鎖
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;
????}
@GetMapping("/delnx/{key}/{val}")
public?int?delnx(@PathVariable?String?key,?@PathVariable?String?val)?{
???return?jedisCom.delnx(key,?val);
}
模擬搶單動作(10w個人開搶)
//總庫存
????private?long?nKuCuen?=?0;
????//商品key名字
????private?String?shangpingKey?=?"computer_key";
????//獲取鎖的超時時間?秒
????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;
????}
/**
?????*?模擬搶單動作
?????*
?????*?@param?b
?????*?@return
?????*/
????private?String?qiang(String?b)?{
????????//用戶開搶時間
????????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;
????????????????????}
????????????????????//模擬生成訂單耗時操作,方便查看:神牛-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沒拿到鎖,在超時范圍內(nèi)繼續(xù)請求鎖,不需要處理
//????????????????if?(b.equals("神牛-50")?||?b.equals("神牛-69"))?{
//????????????????????logger.info("用戶{}等待獲取鎖...",?b);
//????????????????}
????????????}
????????}
????????return?"";
????}


往期熱門文章:
1、滴滴程序員被親戚鄙視:年薪八十萬還不如二本教書的... 2、IT界驚現(xiàn)文豪!華為領(lǐng)導(dǎo)及阿里P10遭吐槽
3、上海地鐵乘車碼“變紅”,嚇倒一眾乘客,官方:為營造節(jié)日氣氛…… 4、Spring Boot 項目打成 .exe 程序?實戰(zhàn)來了! 5、Spring Boot太重,Vert.x真香! 6、中美程序員不完全對比 7、Spring Boot 3.0 M1 發(fā)布,正式棄用 Java 8,最低要求 Java 17。。。 8、一個“扛住100億次請求”的春晚紅包系統(tǒng) 9、你覺得HTTPS能防止重放攻擊嗎? 10、數(shù)據(jù)一致性,為什么不推薦雙寫?
評論
圖片
表情
