網(wǎng)站模板設(shè)計(jì)開發(fā)站長工具四葉草
推薦鏈接:
????總結(jié)——》【Java】
????總結(jié)——》【Mysql】
????總結(jié)——》【Redis】
????總結(jié)——》【Kafka】
????總結(jié)——》【Spring】
????總結(jié)——》【SpringBoot】
????總結(jié)——》【MyBatis、MyBatis-Plus】
????總結(jié)——》【Linux】
????總結(jié)——》【MongoDB】
????總結(jié)——》【Elasticsearch】
Redis——》死鎖
- 一、死鎖場景
- 二、如何避免死鎖
- 1、兩條命令實(shí)現(xiàn):SETNX加鎖 + EXPIRE過期時(shí)間
- (1)實(shí)現(xiàn)
- (2)優(yōu)點(diǎn)
- (3)缺點(diǎn)
- 2、一條命令實(shí)現(xiàn):SET加鎖 + EXPIRE過期時(shí)間
- (1)實(shí)現(xiàn)
- (2)優(yōu)點(diǎn)
- (3)缺點(diǎn)
一、死鎖場景
// 加鎖
SETNX lock_key 1// 業(yè)務(wù)邏輯
DO THINGS// 釋放鎖,刪除key
DEL lock_key
以下情況會(huì)導(dǎo)致已經(jīng)獲得鎖的客戶端一直占用鎖,其他客戶端永遠(yuǎn)無法獲取到鎖,這就是死鎖:
- 程序處理業(yè)務(wù)邏輯異常,沒及時(shí)釋放鎖
- 進(jìn)程掛了,沒機(jī)會(huì)釋放鎖
二、如何避免死鎖
方案:給鎖設(shè)置一個(gè)過期時(shí)間
示例:假設(shè)操作共享資源的時(shí)間不會(huì)超過10s,那么加鎖時(shí),給這個(gè)key設(shè)置10s過期。
1、兩條命令實(shí)現(xiàn):SETNX加鎖 + EXPIRE過期時(shí)間
(1)實(shí)現(xiàn)
SETNX lock_key 1 // 加鎖
EXPIRE lock_key 10 // 10s后自動(dòng)過期
(2)優(yōu)點(diǎn)
鎖可以被自動(dòng)釋放,其它客戶端依舊可以拿到鎖
(3)缺點(diǎn)
如果過期時(shí)間設(shè)置失敗,依舊發(fā)生死鎖問題。
原因:
加鎖、設(shè)置過期時(shí)間是2條命令,這2條命令不能保證是原子操作(一起成功),有可能只執(zhí)行了第一條,第二條卻執(zhí)行失敗
場景:
- SETNX執(zhí)行成功,執(zhí)行EXPIRE時(shí)由于網(wǎng)絡(luò)問題,執(zhí)行失敗
- SETNX執(zhí)行成功,Redis異常宕機(jī),EXPIRE沒有機(jī)會(huì)執(zhí)行
- SETNX執(zhí)行成功,客戶端異常崩潰,EXPIRE沒有機(jī)會(huì)執(zhí)行
2、一條命令實(shí)現(xiàn):SET加鎖 + EXPIRE過期時(shí)間
在Redis 2.6.12之后,Redis擴(kuò)展了SET命令的參數(shù),可以在SET的同時(shí)指定EXPIRE時(shí)間,這條操作是原子的。
(1)實(shí)現(xiàn)
SET lock_key 1 EX 10 NX // 10s后自動(dòng)過期
(2)優(yōu)點(diǎn)
解決死鎖問題
(3)缺點(diǎn)
可能發(fā)生釋放別人的鎖(參考鏈接:Redis——》鎖被別人釋放)