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