python 通過redis實現分佈式鎖案例(setnx)

環境:python3

實現原理:WATCH, MULTI, EXEC, DISCARD事務機制實現分佈式鎖

 

MULTI 、 EXEC 、 DISCARD 和 WATCH 是 Redis 事務的基礎。

事務可以一次執行多個命令, 並且帶有以下兩個重要的保證:

  • 事務是一個單獨的隔離操作:事務中的所有命令都會序列化、按順序地執行。事務在執行的過程中,不會被其他客戶端發送來的命令請求所打斷。

  • 事務是一個原子操作:事務中的命令要麼全部被執行,要麼全部都不執行。

    EXEC 命令負責觸發並執行事務中的所有命令:

    • 如果客戶端在使用 MULTI 開啓了一個事務之後,卻因爲斷線而沒有成功執行 EXEC ,那麼事務中的所有命令都不會被執行。
    • 另一方面,如果客戶端成功在開啓事務之後執行 EXEC ,那麼事務中的所有命令都會被執行。
import uuid
import redis
import time

redis_client=redis.Redis(host='localhost', port=6379)


#  獲取一個分佈式鎖
def acquire_lock(lock_name, acquire_time=10, time_out=10):
    # 生成唯一id
    identifier = str(uuid.uuid4())
    # 客戶端獲取鎖的結束時間
    end = time.time() + acquire_time
    # key
    lock_names = "lock_name:" + lock_name
    while time.time() < end:
        # setnx(key,value) 只有key不存在情況下,將key的值設置爲value,若key存在則不做任何動作,返回True和False
        if redis_client.setnx(lock_names, identifier):
            # 設置鍵的過期時間,過期自動剔除,釋放鎖
            redis_client.expire(lock_names, time_out)
            return identifier
        # 當鎖未被設置過期時間時,重新設置其過期時間
        elif redis_client.ttl(lock_names)==-1:
            redis_client.expire(lock_names, time_out)
        time.sleep(0.001)
    return False


# 鎖的釋放
def release_lock(lock_name, identifire):
    lock_names = "lock_name:" + lock_name
    pipe = redis_client.pipeline(True)
    while True:
        try:
            # 通過watch命令監視某個鍵,當該鍵未被其他客戶端修改值時,事務成功執行。當事務運行過程中,發現該值被其他客戶端更新了值,任務失敗
            pipe.watch(lock_names)
            if pipe.get(lock_names) == identifire:  # 檢查客戶端是否仍然持有該鎖
                # multi命令用於開啓一個事務,它總是返回ok
                # multi執行之後, 客戶端可以繼續向服務器發送任意多條命令, 這些命令不會立即被執行, 而是被放到一個隊列中, 當 EXEC 命令被調用時, 所有隊列中的命令纔會被執行
                pipe.multi()
                # 刪除鍵,釋放鎖
                pipe.delete(lock_names)
                # execute命令負責觸發並執行事務中的所有命令
                pipe.execute()
                return True
            pipe.unwatch()
            break
        except redis.exceptions.WatchError:
            # # 釋放鎖期間,有其他客戶端改變了鍵值對,鎖釋放失敗,進行循環
            pass
    return False

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章