一、什么是分布式鎖
分布式鎖指的是在分布式場景中實現互斥類型的鎖。
分布式是什么意思?分布式表示運行的節點可能在不同的機器或不同的網段中,節點間通信通過socket。互斥類型是什么意思?互斥類型表示同一時刻只允許一個執行體進入臨界資源。
二、分布式鎖的特性
分布式鎖具有三大特性:
1、互斥性:同上所述,互斥性要求同一時刻只允許一個執行體進入臨界資源。具體的操作包括加鎖、解鎖、給執行體打上唯一標記。
2、鎖超時性:由于其分布式的特性(節點間需要通過網絡進行通信),而一旦某獲取了鎖的節點出現網絡故障或者進程宕機,從而無法釋放鎖,這將導致其他嘗試獲取該鎖的節點或進程一直阻塞。因此,為避免該情況的發生,需要對其設置鎖超時特性,即在某節點獲取鎖的時候設定一個時間,當超過該時間后該節點自動釋放鎖資源。
3、可用性:通俗來講就是在合理時間內得到合理的回復。具體展開來又可細分為:
- 高可用性:確保即使部分節點故障,鎖的機制仍然能保持有效,避免系統宕機。
- 網絡分區容忍性:能夠合理處理網絡分區情況,確保系統的正常運行。
- 死鎖防止:通過超時機制等方式,避免死鎖的發生。
- 性能和響應時間:保持高效的鎖操作,減少性能開銷。
三、解決了什么問題?
在分布式場景下,只允許一個節點執行某類任務。
四、分布式鎖的實現問題
常見的分布式鎖的實現方式為:
- 基于 Redis 實現分布式鎖
- 基于 ZooKeeper 實現分布式鎖
- 基于 Etcd 實現分布式鎖
- 基于 Mysql 實現分布式鎖
看到這讀者是否有產生跟我一樣的疑問:分布式鎖在層次結構上應屬于“基礎組件”層次,而redis,mysql這些屬于“中間件”層次,正常來說,中間件是在基礎組件的基礎上實現的,那為什么這里反而是基于中間件去實現基礎組件呢??
原因在于,像redis這樣的中間件,它們提供了構建分布式鎖所需的原子操作,而這些原子操作是實現分布式鎖的基礎。換句話說,redis等這些中間件,它們的某些功能(SETNX EXPIRE)可以非常有效的用于實現分布式鎖,我們基于redis實現分布式鎖就是基于這些他們自帶的功能。
這里以使用redis實現分布式鎖舉例:
import redis
import uuid
import time# 創建 Redis 連接
r = redis.StrictRedis(host='localhost', port=6379, db=0)lock_key = "my_lock"
lock_value = str(uuid.uuid4()) # 鎖的唯一標識
lock_timeout = 10 # 鎖的超時時間(秒)# 獲取鎖
def acquire_lock():# 使用 SETNX 設置鎖并設置過期時間if r.setnx(lock_key, lock_value):r.expire(lock_key, lock_timeout)return Truereturn False# 釋放鎖
def release_lock():# 只有鎖的持有者才能釋放鎖if r.get(lock_key) == lock_value:r.delete(lock_key)# 使用鎖
if acquire_lock():try:print("Lock acquired, doing work...")time.sleep(5) # 模擬任務執行finally:release_lock()print("Lock released")
else:print("Unable to acquire lock")
SETNX
:用于設置一個值,僅當該鍵不存在時才設置。如果 Redis 返回True
,則表示鎖成功獲取;否則,表示鎖已被其他客戶端占用。expire
:為鎖設置超時時間,避免死鎖發生。如果客戶端崩潰或網絡中斷,鎖會在超時后自動釋放。DEL
:釋放鎖時,首先需要檢查當前鎖值是否與客戶端的值匹配,防止誤刪其他客戶端的鎖。
綜上所述:?
- Redis 本身并沒有直接提供“分布式鎖”功能,但它提供了支持實現分布式鎖所需的基礎操作(如
SETNX
、EXPIRE
)。 - 基于這些操作,我們可以構建一個分布式鎖系統。因此,可以說 Redis 提供了實現分布式鎖的基礎構建塊,但實現分布式鎖的功能依賴于如何使用這些操作。
?如果希望使用一個現成的分布式鎖庫,可以選擇 Redisson,它是基于 Redis 的高層次封裝,提供了直接的分布式鎖功能。