redis 事務(悲觀鎖和樂觀鎖)


MULTI

  開啟事務,后續的命令會被加入到同一個事務中

  事務中的操作會發送給客服端,但是不會立即執行,而是將操作放到了該事務對應的一個隊列中,服務端返回QUEQUD

 

EXEC

  執行EXEC后,事務中的命令才會執行

  事務中的命令出錯時,不會回滾也不會停止,而是繼續執行下一步操作

 

DISCARD

  取消事務,事務隊列會被清空

 

原子性:不支持,不會回滾且繼續執行,

隔離性:支持,事務中的命令順序,不會被打斷,先EXEC先執行,單機redis讀寫操作使用單進程單線程

持久性:不支持,redis 數據容易丟失

一致性:不支持,要求通過樂觀鎖watch來實現

 

redis 非 事務型管道:

from redis import StrictRedis

# 創建redis客戶端 decode_response = true 從redis中獲取的數據會進行decorade,不會是byse類型
redis_client = StrictRedis(host='127.0.0.1',port=6379,db=0,decode_response=True)

# 創建管道  默認就會開啟事務,(設置參數,transaction=False,則不會開啟事務,只會開啟管道)
pipe = redis_client.pipeline(transaction=False)

# 使用管道對象進行的操作
a = pipe.set('name', 'zhangsan')
b = pipe.get('name')

# 不會提交事務  只是將管道打包提交給redis服務器
c = pipe.execute()

print(a, b, c)

 事務型管道:

#創建客服端
redis_client = StrictRedis()

#創建管道,默認會開啟事務
pipe = redis_client.pipeline()

#使用管道對象進行操作,都會放入事務中
a = pipe.set('name':'zs')
b = pipe.get('name')

#提交事務,提交事務后才會執行
c = pipe.execute()
print(a,b,c)

 

樂觀鎖:watch

  redis實現樂觀鎖機制

  機制:開啟事務前,設置對數據的監聽,EXEC時,如果發生數據發生過修改,事務會自動取消(DISCARD)

  事務EXEC后,無論成敗,監聽會被移除

redis 樂觀鎖代碼:

from redis import StrictRedis, WatchError

# 創建客戶端
redis_client = StrictRedis(host='127.0.0.1',port=6379,db=0,)
# 創建管道
pipe = redis_client.pipeline()


while True:
    try:
        # 開啟數據的監聽  一旦調用watch, 后續操作會立即執行(后續操作不會添加到事務中)
        pipe.watch('reserve_count')

        # 獲取庫存數量
        count = pipe.get('reserve_count')
        # 判斷是否有庫存
        if int(count) > 0: # 有庫存, 讓庫存 -1

            # 手動開啟事務
            pipe.multi()

            # 庫存-1
            pipe.decr('reserve_count')

            # 提交事務
            pipe.execute()
            print('已下單')

        else:  # 沒有庫存
            print('已售罄')
            # 移除監聽
            pipe.reset()

        break

    except WatchError as e:  # 出現該異常, 說明監聽的數據被修改了, 重試/取消
        print('重試')

 

 

悲觀鎖: setnx 建不存在才會設置成功

setnx和redis 悲觀鎖代碼   

from redis import StrictRedis

# 創建redis連接
redis_client = StrictRedis(decode_responses=True)

# 設計redis悲觀鎖 處理秒殺超賣問題

# 先獲取鎖
while True:
    order_lock = redis_client.setnx('lock:order', 1)
redis_client.expire(
'lock:order', 2) # 給鎖設置過期時間, 避免鎖釋放失敗導致死鎖現象 if order_lock: reserve_count = redis_client.get('reserve_count') if int(reserve_count) > 0: redis_client.decr('reserve_count') print("生成訂單") else: print("已售罄") # 完成處理, 移除鎖 redis_client.delete('lock:order') break

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM