亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Java使用Redis實(shí)現(xiàn)秒殺功能

瀏覽:2日期:2022-08-23 14:24:44

秒殺功能

秒殺場(chǎng)景現(xiàn)在已經(jīng)非常常見了,各種電商平臺(tái)都有秒殺的產(chǎn)品,接下來(lái)我們模擬一個(gè)秒殺的項(xiàng)目,最終能夠確保高并發(fā)下的線程安全。界面比較簡(jiǎn)單,但是功能基本實(shí)現(xiàn)。

界面

Java使用Redis實(shí)現(xiàn)秒殺功能

點(diǎn)擊“秒殺點(diǎn)我”按鈕后臺(tái)就會(huì)輸出秒殺結(jié)果。

Java使用Redis實(shí)現(xiàn)秒殺功能

第一版

使用Redis緩存數(shù)據(jù)庫(kù),使用一個(gè)key-value存儲(chǔ)秒殺商品數(shù)量,使用set集合存儲(chǔ)秒殺成功的用戶。我們以商品0101為示例,設(shè)置商品的初始數(shù)量為200件。不考慮并發(fā)問(wèn)題,實(shí)現(xiàn)功能。

html、jsp、servlet文件不重要省略。

package com.redis.secondskill; import java.util.List; import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPool;import redis.clients.jedis.Transaction; public class SS0 { public static boolean doSecKill(String uid,String prodid) { JedisPool jedisPool = JedisPollTool.getInstance(); Jedis jedis = jedisPool.getResource(); String productCountStr = 'sec:'+prodid+':count'; String productUserStr = 'sec:'+prodid+':user'; String productCount = jedis.get(productCountStr); if(null == productCount) { System.out.println('秒殺還沒有開始'); JedisPollTool.distroy(jedisPool, jedis); return false; } if(jedis.sismember(productUserStr, uid)) { System.out.println(uid + '用戶已經(jīng)秒殺成功'); JedisPollTool.distroy(jedisPool, jedis); return false; } int prodCount = Integer.parseInt(productCount); if(prodCount <= 0) { System.out.println('秒殺結(jié)束'); JedisPollTool.distroy(jedisPool, jedis); return false; } jedis.decr(productCountStr); jedis.sadd(productUserStr, uid); JedisPollTool.distroy(jedisPool, jedis); System.out.println(uid + '秒殺成功'); return true; }}

使用linux httpd-tools工具進(jìn)行并發(fā)測(cè)試。

ab -n 1000 -c 200 -p /test/file.txt -T 'application/x-www-form-urlencoded' 192.168.0.101:8080/redis-demo/ss

結(jié)果

Java使用Redis實(shí)現(xiàn)秒殺功能

從結(jié)果大致來(lái)看,沒有什么問(wèn)題,來(lái)查看一個(gè)后臺(tái)Redis的數(shù)據(jù)

秒殺的結(jié)果里面居然有負(fù)數(shù),證明賣超了。

Java使用Redis實(shí)現(xiàn)秒殺功能

第二版

使用Redis的事務(wù),保證沒有超賣的情況發(fā)生。

package com.redis.secondskill; import java.util.List; import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPool;import redis.clients.jedis.Transaction; public class SS1 { public static boolean doSecKill(String uid,String prodid) { JedisPool jedisPool = JedisPollTool.getInstance(); Jedis jedis = jedisPool.getResource(); String productCountStr = 'sec:'+prodid+':count'; String productUserStr = 'sec:'+prodid+':user'; jedis.watch(productCountStr); //開始監(jiān)視 String productCount = jedis.get(productCountStr); if(null == productCount) { System.out.println('秒殺還沒有開始'); JedisPollTool.distroy(jedisPool, jedis); return false; } if(jedis.sismember(productUserStr, uid)) { System.out.println(uid + '用戶已經(jīng)秒殺成功'); JedisPollTool.distroy(jedisPool, jedis); return false; } int prodCount = Integer.parseInt(productCount); if(prodCount <= 0) { System.out.println('秒殺結(jié)束'); JedisPollTool.distroy(jedisPool, jedis); return false; } Transaction transaction = jedis.multi(); transaction.decr(productCountStr); transaction.sadd(productUserStr, uid); List<Object> exec = transaction.exec(); if(exec == null || exec.size() == 0) { System.out.println('秒殺失敗,稍后重試'); JedisPollTool.distroy(jedisPool, jedis); return false; } JedisPollTool.distroy(jedisPool, jedis); System.out.println(uid + '秒殺成功'); return true; }}

結(jié)果

Java使用Redis實(shí)現(xiàn)秒殺功能

由于使用了watch和事務(wù),每次的并發(fā)線程訪問(wèn)中只有一個(gè)線程能夠提交成功,可以保證不出現(xiàn)超賣的現(xiàn)象,但是對(duì)于一些用戶來(lái)說(shuō)是極其不公平的。

第三版

使用Lua腳本來(lái)實(shí)現(xiàn),因?yàn)镽edis是單線程的,又是C語(yǔ)言編寫的,可以使用Lua調(diào)用Redis的命令,Lua會(huì)具有排他性,所以能夠保證安全。

package com.redis.secondskill; import java.util.HashSet;import java.util.Set; import redis.clients.jedis.HostAndPort;import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPool; public class SS2 { static String luaScript ='local userid=KEYS[1];rn' + 'local prodid=KEYS[2];rn' + 'local qtkey=’sec:’..prodid..':count';rn' + 'local usersKey=’sec:’..prodid..':user';rn' + 'local userExists=redis.call('sismember',usersKey,userid);rn' + 'if tonumber(userExists)==1 then rn' + ' return 2;rn' + 'endrn' + 'local num = redis.call('get' ,qtkey);rn' + 'if tonumber(num)<=0 then rn' + ' return 0;rn' + 'else rn' + ' redis.call('decr',qtkey);rn' + ' redis.call('sadd',usersKey,userid);rn' + 'endrn' + 'return 1' ; public static boolean doSecKill(String uid,String prodid) { JedisPool jedisPool = JedisPollTool.getInstance(); Jedis jedis = jedisPool.getResource(); String sha1 = jedis.scriptLoad(luaScript); Object result= jedis.evalsha(sha1, 2, uid,prodid); String reString=String.valueOf(result); if ('0'.equals( reString ) ) { System.err.println('已搶空!!'); }else if('1'.equals( reString ) ) { System.out.println(uid + '搶購(gòu)成功!!!!'); }else if('2'.equals( reString ) ) { System.err.println('該用戶已搶過(guò)!!'); }else{ System.err.println('搶購(gòu)異常!!'); } JedisPollTool.distroy(jedisPool, jedis); return true; }}

結(jié)果

Java使用Redis實(shí)現(xiàn)秒殺功能

這才是我們最希望看到的結(jié)果!

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 黄色片xxx | 中日韩欧美视频 | 91精品国产9l久久久久 | 国产国产成人久久精品杨幂 | 久久成人精品免费播放 | 免费观看日批视频 | 国产私拍精品88福利视频 | 国产91精品露脸国语对白 | 国产毛片视频 | 伊人精品综合 | 欧美一级毛片一级 | 天堂影院jav成人天堂免费观看 | 亚洲啪啪 | 国产免费久久精品99久久 | 五月久久噜噜噜色影 | 欧美日韩国产58香蕉在线视频 | 国产一区二区在线视频观看 | 的九一视频入口在线观看 | 国产 欧美 日韩在线 | 亚洲爆乳无码一区二区三区 | 日韩高清中文字幕 | 国产成人精品日本亚洲麻豆 | 免费一级a毛片在线播放 | 在线国产一区二区 | 美女毛片在线 | 久久婷婷综合中文字幕 | 久久r这里只有精品 | 在线观看免费精品国产 | 亚洲成人在线播放 | 看一级毛片一区二区三区免费 | 日本成a人片在线观看网址 日本成人一区二区 | 免费毛片软件 | 草草在线观看视频 | 香蕉久久精品国产 | 久久精品道一区二区三区 | 国产www色| 国产精品免费视频播放器 | 国产91福利 | 91精品一区二区三区在线观看 | 福利在线不卡 | 久久精品a亚洲国产v高清不卡 |