《Redis深度歷險》二(分布式鎖)

2022-07-11 22:06:14 字數 1977 閱讀 8628

redis命令積累

本質上就是在redis裡面佔乙個坑,別的程序要進來時,發現已經有人在了,只好放棄或稍後再試。

setnx

setnx lock true

do sth

del lock

問題:如果中間邏輯出現異常,del將會無法執行,會陷入死鎖

setnx lock true

expire 5

do sth

del lock

問題:如果setnx和expire之間斷掉,沒有執行expre,陷入死鎖

解決:setnx和expire組合的原子指令,也是分布式鎖的奧義

set lock true ex 5 nx

do sth

del lock

redis分布式鎖不能解決超時問題,如果在加鎖和釋放鎖之間的邏輯執行的太長,以至於超出了鎖的超時限制,就會有問題。

解決:使用delifequals釋放鎖,而不是expire,可以傳入key和乙個隨機數來保證釋放鎖的正確性。

tag = random.nextint() // random tag

if redis.set(key,tag,nx=true,ex=5):

do_sth

redis.delifequals(key,tag)

可重入性是指執行緒在持有鎖的情況下再次請求加鎖,如果乙個鎖支援同乙個執行緒的多次加 鎖,那麼這個鎖就是可重入的。redis 分 布式鎖如果要支援可重入,需要對客戶端的 set 方法進行包裝,使用執行緒的 threadlocal 變數 儲存當前持有鎖的計數。

import redis import threading

locks = threading.local()

locks.redis = {}

def key_for(user_id):

return "account_{}".format(user_id)

def _lock(client,key):

return bool(client.set(key,true,nx=true,ex=5))

def _unlock(client,key):

client.delete(key)

def lock(client,user_id):

key = key_for(user_id)

if key in locks.redis: # 若存在則鎖的數量+1

locks.redis[key] += 1

return true

ok = _lock(client,key) # 若不存新增鎖,數量設為1

if not ok:

retrun false

locks.redis[key] = 1

return true

def unlock(client,user_id):

key = key_for(user_id)

if key in locks.redis:

locks.redis[key] -= 1 # 釋放鎖,數量-1

if locks.redis[key] <= 0: # 判斷若小於0,則完全釋放鎖

del locks.redis[key]

return true

return false

client = redis.strictredis()

lock(client,"codehole") # 第一次加鎖,返回true

lock(client,"codehole") # 第二次,鎖的數量+1,返回true

unlock(client,"codehole") # 釋放一把鎖

unlock(client,"codehole") # 完全釋放鎖

Redis(五)分布式鎖

1.分布式鎖是什麼 分布式鎖是控制分布式系統或不同系統之間共同訪問共享資源的一種鎖實現,如果不同的系統或同一系統的不同主機之間共享了某個資源時,往往通過互斥來防止彼此干擾。2.分布式設計目的 可以保證在分布式部署的應用集群中,同乙個方法在同一操作只能被一台機器上的乙個執行緒執行。3.設計要求 1 這...

Redis 應用01 分布式鎖

在處理分布式應用併發的時候,常常會使用鎖。比如我們有個 num 3,應用對num操作 去資料庫取值 取完值,在記憶體中,進行邏輯運算後重新賦值 存回資料庫 當多個應用同時對num操作的時候 比如 a和b 都對num進行操作 取值 a1 b1 賦值 b1 b3 在資料庫操作中,如果執行順序是a1 a3...

redis2 分布式鎖

尚矽谷 陽哥 加鎖 stringredistemplate.opsforvalue setifabsent redis lock key,value setnx 釋放鎖 stringredistemplate.delete redis lock key 釋放鎖 stringredistemplate...