新聞中心
在很多互聯(lián)網(wǎng)產(chǎn)品應(yīng)用中,有些場(chǎng)景需要加鎖處理,比如:秒殺,全局遞增ID,樓層生成等等。大部分的解決方案是基于DB實(shí)現(xiàn)的,Redis為單進(jìn)程單線程模式,采用隊(duì)列模式將并發(fā)訪問(wèn)變成串行訪問(wèn),且多客戶端對(duì)Redis的連接并不存在競(jìng)爭(zhēng)關(guān)系。其次Redis提供一些命令SETNX,GETSET,可以方便實(shí)現(xiàn)分布式鎖機(jī)制。

成都創(chuàng)新互聯(lián)公司專(zhuān)注于企業(yè)成都營(yíng)銷(xiāo)網(wǎng)站建設(shè)、網(wǎng)站重做改版、射陽(yáng)網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5建站、商城建設(shè)、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為射陽(yáng)等各大城市提供網(wǎng)站開(kāi)發(fā)制作服務(wù)。
踩坑1. 數(shù)據(jù)庫(kù)事務(wù)超時(shí)
不要感覺(jué)奇怪,分布式鎖怎么會(huì)導(dǎo)致數(shù)據(jù)庫(kù)事務(wù)超時(shí)呢? 我的代碼大概是這樣的:
偽代碼
@Transaction(readOnly=false)
void update(){
do{
redis=JedisUtil.getJedis();
flag = getLock(key,redis);
if(flag){
update();
}
}while(true)
}
當(dāng)你的key長(zhǎng)時(shí)間獲取不到鎖,并且數(shù)據(jù)庫(kù)事務(wù)都有超時(shí)時(shí)間的限制,那么就會(huì)出現(xiàn)數(shù)據(jù)庫(kù)事務(wù)超時(shí)問(wèn)題; 解決方案
數(shù)據(jù)庫(kù)事務(wù)改為手動(dòng)提交事務(wù);
踩坑2. redis key過(guò)期,而業(yè)務(wù)沒(méi)有執(zhí)行完
我的key的過(guò)期時(shí)間設(shè)置的是30s,如果30秒業(yè)務(wù)還沒(méi)有執(zhí)行完畢,鎖就會(huì)自動(dòng)釋放,鎖釋放之后,其它線程又會(huì)去占用鎖,同樣會(huì)導(dǎo)致問(wèn)題的發(fā)生; 解決方案
最簡(jiǎn)單的解決方案就是使用redisson; 如果非要用redis來(lái)解決的話,只能使用定時(shí)器去檢測(cè)key,如果說(shuō)key還有2秒就快過(guò)期了,那么再為key重新設(shè)置30秒的過(guò)期時(shí)間;
踩坑3. redis連接池爆滿
分布式鎖剛加上之后,生產(chǎn)出現(xiàn)一個(gè)問(wèn)題,就是:redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool 解決辦法 開(kāi)始查代碼,發(fā)現(xiàn)是開(kāi)發(fā)人員沒(méi)有對(duì)連接進(jìn)行釋放;
修復(fù)bug之后,又在線上跑了一段時(shí)間,又出現(xiàn)了redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool 解決辦法
void update(){
do{
redis=JedisUtil.getJedis();
flag = getLock(key,redis);
if(flag){
update();
}else{
// 釋放當(dāng)前redis連接
// 由于我們的業(yè)務(wù)場(chǎng)景屬于比較耗時(shí)的業(yè)務(wù)型,所以在這里休眠1000毫秒
redis.close();
sleep(1000);
}
}while(true)
}
1.當(dāng)前請(qǐng)求獲取鎖,如果獲取不到,則釋放當(dāng)前連接,并休眠一會(huì); 2.合理配置redis連接池大小,主要參考具體業(yè)務(wù)場(chǎng)景的并發(fā)量來(lái)設(shè)置;
踩坑4. 解鈴還須系鈴人
回顧一下加鎖的參數(shù):
set(key, vlue,"NX","PX", 30000);
其中:value,我使用它來(lái)表示加鎖人,必須是一個(gè)唯一的標(biāo)識(shí)
比如: A線程 key=test value=01 B線程 key=test value=02
如果A線程執(zhí)行業(yè)務(wù)耗時(shí)超過(guò)了鎖的持有時(shí)間,鎖會(huì)自動(dòng)釋放;鎖自動(dòng)釋放之后,線程B又加鎖成功,但是,此時(shí)A線程執(zhí)行完業(yè)務(wù)邏輯之后,去釋放鎖,但A線程的鎖已經(jīng)自動(dòng)釋放了,如果沒(méi)有value來(lái)標(biāo)識(shí)的話,它可能就會(huì)去釋放B線程的鎖;
踩坑5. redis集群實(shí)現(xiàn)分布式鎖
這種情況我沒(méi)有遇到,因?yàn)楣镜膔edis集群做了改進(jìn);
先說(shuō)一下這種問(wèn)題產(chǎn)生的原因: 如果master節(jié)點(diǎn)由于某原因發(fā)生了主從切換,那么就會(huì)出現(xiàn)鎖丟失的情況;
解決辦法
需要通過(guò)使用redlock算法; 或使用redisson,它有對(duì)redlock算法做封裝;
本文名稱(chēng):Redis實(shí)現(xiàn)分布式鎖具體方法
文章分享:http://www.dlmjj.cn/article/dpgcihd.html


咨詢
建站咨詢
