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

成都創(chuàng)新互聯(lián)公司專注于企業(yè)成都營(yíng)銷網(wǎng)站建設(shè)、網(wǎ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à)比高,為射陽等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。
踩坑1. 數(shù)據(jù)庫(kù)事務(wù)超時(shí)
不要感覺奇怪,分布式鎖怎么會(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í)問題; 解決方案
數(shù)據(jù)庫(kù)事務(wù)改為手動(dòng)提交事務(wù);
踩坑2. redis key過期,而業(yè)務(wù)沒有執(zhí)行完
我的key的過期時(shí)間設(shè)置的是30s,如果30秒業(yè)務(wù)還沒有執(zhí)行完畢,鎖就會(huì)自動(dòng)釋放,鎖釋放之后,其它線程又會(huì)去占用鎖,同樣會(huì)導(dǎo)致問題的發(fā)生; 解決方案
最簡(jiǎn)單的解決方案就是使用redisson; 如果非要用redis來解決的話,只能使用定時(shí)器去檢測(cè)key,如果說key還有2秒就快過期了,那么再為key重新設(shè)置30秒的過期時(shí)間;
踩坑3. redis連接池爆滿
分布式鎖剛加上之后,生產(chǎn)出現(xiàn)一個(gè)問題,就是:redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool 解決辦法 開始查代碼,發(fā)現(xiàn)是開發(fā)人員沒有對(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ā)量來設(shè)置;
踩坑4. 解鈴還須系鈴人
回顧一下加鎖的參數(shù):
set(key, vlue,"NX","PX", 30000);
其中:value,我使用它來表示加鎖人,必須是一個(gè)唯一的標(biāo)識(shí)
比如: A線程 key=test value=01 B線程 key=test value=02
如果A線程執(zhí)行業(yè)務(wù)耗時(shí)超過了鎖的持有時(shí)間,鎖會(huì)自動(dòng)釋放;鎖自動(dòng)釋放之后,線程B又加鎖成功,但是,此時(shí)A線程執(zhí)行完業(yè)務(wù)邏輯之后,去釋放鎖,但A線程的鎖已經(jīng)自動(dòng)釋放了,如果沒有value來標(biāo)識(shí)的話,它可能就會(huì)去釋放B線程的鎖;
踩坑5. redis集群實(shí)現(xiàn)分布式鎖
這種情況我沒有遇到,因?yàn)楣镜膔edis集群做了改進(jìn);
先說一下這種問題產(chǎn)生的原因: 如果master節(jié)點(diǎn)由于某原因發(fā)生了主從切換,那么就會(huì)出現(xiàn)鎖丟失的情況;
解決辦法
需要通過使用redlock算法; 或使用redisson,它有對(duì)redlock算法做封裝;
網(wǎng)站題目:Redis實(shí)現(xiàn)分布式鎖具體方法
網(wǎng)頁(yè)路徑:http://www.5511xx.com/article/dpgcihd.html


咨詢
建站咨詢
