redis分布式鎖

2021-10-08 02:35:22 字數 3294 閱讀 9362

redis分布式鎖要解決的問題:為了保證乙個方法或屬性在高併發情況下的同一時間只能被同乙個執行緒執行,在傳統單體應用單機部署的情況下,可以使用併發處理相關的功能進行互斥控制。但是,隨著業務發展的需要,原單體單機部署的系統被演化成分布式集群系統後,由於分布式系統多執行緒、多程序並且分布在不同機器上,這將使原單機部署情況下的併發控制鎖策略失效,單純的應用並不能提供分布式鎖的能力。為了解決這個問題就需要一種跨機器的互斥機制來控制共享資源的訪問,這就是分布式鎖要解決的問題!(可以保證在分布式部署的應用集群中,同乙個方法在同一操作只能被一台機器上的乙個執行緒執行,在傳統的基於資料庫的架構中,對於資料的搶占問題往往是通過資料庫事務(acid)來保證的。在分布式環境中,出於對效能以及一致性敏感度的要求,使得分布式鎖成為了一種比較常見而高效的解決方案)

分布式鎖應該具備哪些條件:

高可用的獲取鎖與釋放鎖

高效能的獲取鎖與釋放鎖

具備可重入特性

具備鎖失效機制,防止死鎖

具備非阻塞鎖特性,即沒有獲取到鎖將直接返回獲取鎖失敗

選用redis實現分布式鎖原因:

redis有很高的效能

redis命令對此支援較好,實現起來比較方便

redis分布式鎖常見命令

setnx: setnx key val:當且僅當key不存在時,建立乙個kv的字串鎖,返回1;若key存在,則什麼都不做,返回0

expire:expire key timeout:為key設定乙個超時時間,單位為second,超過這個時間鎖會自動釋放,避免死鎖

delete:delete key:刪除key

設計思想:

獲取鎖的時候,使用setnx加鎖,並使用expire命令為鎖新增乙個超時時間,超過該時間則自動釋放鎖,鎖的value值為乙個隨機生成的uuid,通過value在釋放鎖的時候進行判斷

獲取鎖的時候還設定乙個獲取的超時時間,若超過這個時間則放棄獲取鎖

釋放鎖的時候,通過uuid判斷是不是該鎖,若是該鎖,則執行delete進行鎖釋放

**(50個使用者或執行緒搶10張票):

import time

import uuid

from threading import thread

import redis

redis_client = redis.redis(host=

"localhost"

, port=

6379

, db=0)

#獲取乙個鎖

# lock_name:鎖定名稱

# acquire_time: 客戶端等待獲取鎖的時間

# time_out: 鎖的超時時間

defacquire_lock

(lock_name, acquire_time=

10, time_out=10)

:"""獲取乙個分布式鎖"""

identifier =

str(uuid.uuid4())

end = time.time(

)+ acquire_time

lock =

"string:lock:"

+ lock_name

while time.time(

)< end:

if redis_client.setnx(lock, identifier)

:# 給鎖設定超時時間, 防止程序崩潰導致其他程序無法獲取鎖

redis_client.expire(lock, time_out)

return identifier

elif

not redis_client.ttl(lock)

: redis_client.expire(lock, time_out)

time.sleep(

0.001

)return

false

#釋放乙個鎖

defrelease_lock

(lock_name, identifier)

:"""通用的鎖釋放函式"""

lock =

"string:lock:"

+ lock_name

pip = redis_client.pipeline(

true

)while

true

:try

: pip.watch(lock)

# 對key進行監視,監視乙個(或多個) key ,如果在事務執行之前這個(或這些) key 被其他命令所改動,那麼事務將被打斷

lock_value = redis_client.get(lock)

ifnot lock_value:

return

true

if lock_value.decode(

)== identifier:

pip.multi(

)# 開啟事務

pip.delete(lock)

pip.execute(

)# 提交事務

return

true

pip.unwatch(

)# 取消監視

break

except redis.excetions.wacthcerror:

pass

return

false

count =

10def

seckill

(i):

identifier=acquire_lock(

'resource'

)print

("執行緒:{}--獲得了鎖"

.format

(i))

time.sleep(1)

global count

if count <1:

print

("執行緒:{}--沒搶到,票搶完了"

.format

(i))

return

count-=

1print

("執行緒:{}--搶到一張票,還剩{}張票"

.format

(i,count)

) release_lock(

'resource'

,identifier)

for i in

range(50

):t = thread(target=seckill,args=

(i,)

) t.start(

)

redis分布式鎖

redis分布式鎖 直接上 我寫了四個redis分布式鎖的方法,大家可以提個意見 第一種方法 redis分布式鎖 param timeout public void lock long timeout thread.sleep 100 catch exception e override publi...

Redis分布式鎖

分布式鎖一般有三種實現方式 1.資料庫樂觀鎖 2.基於redis的分布式鎖 3.基於zookeeper的分布式鎖.首先,為了確保分布式鎖可用,我們至少要確保鎖的實現同時滿足以下四個條件 互斥性。在任意時刻,只有乙個客戶端能持有鎖。不會發生死鎖。即使有乙個客戶端在持有鎖的期間崩潰而沒有主動解鎖,也能保...

redis分布式鎖

使用redis的setnx命令實現分布式鎖 redis為單程序單執行緒模式,採用佇列模式將併發訪問變成序列訪問,且多個客戶端對redis的連線並不存在競爭關係。redis的setnx命令可以方便的實現分布式鎖。setnx key value 將key的值設為value,當且僅當key不存在。如給定的...