redis鎖處理高并發(fā)問題十分常見,使用的時候常見有幾種錯誤创淡,和對應(yīng)的解決辦法蔓腐,在此進(jìn)行自己的總結(jié)和整理灌砖。
set方式
setnx方式
setnx+getset方式
set方式?
作為redis小白望侈,一開始能想到的使用redis加鎖的方式就是set具练。?
加鎖:redis中set一個值,set(lock甜无,1);?
并發(fā)處理:其他線程必須拿到這個值,才可以往下進(jìn)行哥遮,否則等待岂丘。
釋放鎖:執(zhí)行完業(yè)務(wù)代碼之后,釋放redis鎖眠饮,jedis.del(lock)?
防止死鎖:set(lock,1) —>3秒后未釋放奥帘,則自動釋放setex(lock, 3, 1)?
問題:高并發(fā)情況下,進(jìn)程同時獲取鎖狀態(tài)為null仪召,同時設(shè)置寨蹋,鎖之間相互覆蓋,但是倆進(jìn)程仍在并發(fā)執(zhí)行業(yè)務(wù)代碼扔茅。?
setnx方式?
后來發(fā)現(xiàn)有setnx的原子操作命令已旧,鎖存在不能設(shè)置值,返回0召娜;鎖不存在运褪,則設(shè)置鎖,返回1玖瘸;?
加鎖:jedis.setnx(lock, 1)?
并發(fā)處理:
釋放鎖:執(zhí)行完業(yè)務(wù)代碼之后秸讹,釋放redis鎖,jedis.del(lock)?
問題:當(dāng)進(jìn)程執(zhí)行出現(xiàn)問題雅倒,鎖未釋放璃诀,則其他進(jìn)程永遠(yuǎn)處于阻塞狀態(tài),出現(xiàn)死鎖蔑匣。?
防止死鎖:加鎖時帶上時間戳劣欢,setnx(lock, 時間戳+超時時間)
問題:當(dāng)倆進(jìn)程同時讀到發(fā)現(xiàn)鎖超時,都去釋放鎖裁良,相互覆蓋氧秘,則倆進(jìn)程同時獲得鎖,仍并發(fā)執(zhí)行業(yè)務(wù)代碼趴久。?
setnx+getset方式?
為解決上面的問題丸相,可以使用getset命令,getset設(shè)置鍵值彼棍,并返回原來的鍵值灭忠。?
加鎖:setnx(lock, 時間戳+超時時間)?
解決并發(fā):