Redis實現分布式鎖(單機版)

2021-10-05 20:32:17 字數 2705 閱讀 7845

一、前言

在我們日常工作中,除了spring和mybatis外,用到最多無外乎分布式快取框架——redis。但是很多任務作很多年的朋友對redis還處於乙個最基礎的使用和認識。所以我就像把自己對分布式快取的一些理解和應用整理乙個系列,希望可以幫助到大家加深對redis的理解。本系列的文章思路先從redis的應用開始。再解析redis的內部實現原理。最後以經常會問到redis相關的面試題為結尾。

二、分布式鎖的實現要點

為了實現分布式鎖,需要確保鎖同時滿足以下四個條件:

互斥性:在任意時刻,只有乙個客戶端能持有鎖

不會發生死鎖:即使乙個客戶端持有鎖的期間崩潰而沒有主動釋放鎖,也需要保證後續其他客戶端能夠加鎖成功

加鎖和解鎖必須是同乙個客戶端,客戶端自己不能把別人加的鎖給釋放了。

容錯性:只要大部分的redis節點正常執行,客戶端就可以進行加鎖和解鎖操作。

三、redis實現分布式鎖

加鎖操作:

1.使用setnx命令保證互斥性

2.需要設定鎖的過期時間,避免死鎖

3.setnx和設定過期時間需要保持原子性,避免在設定setnx成功之後在設定過期時間客戶端崩潰導致死鎖

4.加鎖的value 值為乙個唯一標示。可以採用uuid作為唯一標示。加鎖成功後需要把唯一標示返回給客戶端來用來客戶端進行解鎖操作

解鎖操作:

1.需要拿加鎖成功的唯一標示要進行解鎖,從而保證加鎖和解鎖的是同乙個客戶端

2. 解鎖操作需要比較唯一標示是否相等,相等再執行刪除操作。這2個操作可以採用lua指令碼方式使2個命令的原子性。

**實現:

public

inte***ce

distributedlock

/** * @author zhi.li

* @description

* @created 2019/1/1 20:32

*/@slf4j

public

class

redisdistributedlock

implements

distributedlock

/** * 獲取指定鍵值的鎖,同時設定獲取鎖超時時間

* @param jedis jedis redis客戶端

* @param lockkey 鎖的鍵值

* @param acquiretimeout 獲取鎖超時時間

*/public

redisdistributedlock

(jedis jedis,string lockkey,

int acquiretimeout)

/** * 獲取指定鍵值的鎖,同時設定獲取鎖超時時間和鎖過期時間

* @param jedis jedis redis客戶端

* @param lockkey 鎖的鍵值

* @param acquiretimeout 獲取鎖超時時間

* @param expiretime 鎖失效時間

*/public

redisdistributedlock

(jedis jedis, string lockkey,

int acquiretimeout,

int expiretime)

@override

public string acquire()

trycatch

(interruptedexception e)}}

catch

(exception e)

return null;

}@override

public

boolean

release

(string identify)

string script =

"if redis.call('get', keys[1]) == ar**[1] then return redis.call('del', keys[1]) else return 0 end"

; object result =

newobject()

;try

", identify)

;return

true;}

}catch

(exception e)

finally

} log.

info

("release lock failed, requesttoken:{}, result:{}"

, identify, result)

;return

false;}

}  下面就以秒殺庫存數量為場景,測試下上面實現的分布式鎖的效果。具體測試**如下:

public

class

redisdistributedlocktest

public

static

void

main

(string[

] args)

finally}}

;for

(int i =

0; i <

10; i++)}

}

單機Redis實現分布式鎖

最近有個專案用到了鎖,直接想到了redis,在網上檢視了一下案列,總感覺不是特別符合需求,索性自己寫了乙個。不多說,直接上 class redis lock 單機redis 分布式鎖 class redis lock 單台redis設定鎖 param string key param int exp...

redis單機實現分布式鎖

原理 使用setnx,設定成功返回1,失敗返回0,由於redis也是單執行緒的,所以一次只能有乙個執行緒獲取成功。程式異常情況 設定超時時間,避免程式掛掉鎖無法釋放。執行超時情況 為避免 執行時間超過key設定的超時時間,從而釋放了其他程序的鎖問題。需要儲存當前執行緒的value。在釋放之前先檢查k...

redis 單機鎖 和 分布式鎖

偷自 require vendor autoload.php client new predis client scheme tcp host 127.0.0.1 port 6379,class redislock desc 獲取鎖鍵名 public function getlockcachekey...