誰說Redis不支援事務?

Mrrrrr10發表於2019-04-13

一、概述:

概念: 可以一次執行多個命令,本質是一組命令的集合。一個事務中的所有命令都會序列化,按順序地序列化執行而不會被其它命令插入,不許加塞。

Redis部分支援事務,不支援的是:強一致性

能幹嘛: 一個佇列中,一次性、順序性、排他性的執行一系列命令

常用命令:

  • MULTI:開啟一個事務,MULTI 執行之後,客戶端可以繼續向伺服器傳送任意多條命令,這些命令不會立即被執行,而是被放到一個佇列中。
  • EXEC:執行佇列中所有的命令
  • DISCARD:清空事務佇列,並放棄執行事務
  • UNWATCH取消 WATCH 命令對所有 key 的監視
  • WATCH key1 key2 ... :監視一個(或多個) key ,如果在事務執行之前這個(或這些) key 被其他命令所改動,那麼事務將被打斷。

二、使用:

正常執行:

image

放棄事務:

image

全體連坐:

一個指令語法錯誤,注意:我說的是語法錯誤!,EXEC執行報錯。

image

冤頭債主(部分支援事務):

冤有頭,債有主,對的放行,誰錯找誰。這也就說明:Redis部分支援事務,對的放行,錯的報錯。

image

WATCH監控:先監控,後開啟事務

快取的資料,誰都可以拿,可以改,所以必須打標記來監控行為。這裡涉及到鎖的問題:悲觀鎖/樂觀鎖/CAS(Check And Set)

  • 悲觀鎖(Pessimistic Lock): 顧名思義,就是很悲觀,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會block直到它拿到鎖。傳統的關係型資料庫裡邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。
  • 樂觀鎖(Optimistic Lock): 顧名思義,就是很樂觀,每次去拿資料的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下,在此期間別人有沒有去更新這個資料,可以使用版本號等機制。樂觀鎖適用於多讀的應用型別,這樣可以提高吞吐量,
  • 樂觀鎖策略(常用):提交版本必須大於記錄當前版本才能執行更新。這樣既不影響併發性,有可以滿足需求。

案例演示:信用卡和欠額

正常情況:無加塞篡改

image

有加塞篡改的情況:

image

在 WATCH 監控後,有人修改了balance,會導致事務會被打斷,必須更新最新值,才能成功執行事務,類似於樂觀鎖的版本號機制。

事務三階段:

1、開啟:以MULTI開始一個事務

2、入隊:將多個命令入隊到事務中,接到這些命令並不會立即執行,而是放到等待執行的事務佇列裡面

3、執行:由EXEC命令觸發事務

事務三特性:

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

2、沒有隔離級別的概念:佇列中的命令沒有提交之前都不會實際的被執行,因為事務提交前任何指令都不會被實際執行,也就不存在”事務內的查詢要看到事務裡的更新,在事務外查詢不能看到”這個讓人萬分頭痛的問題

3、(重點)不保證原子性:redis同一個事務中如果有一條命令執行失敗,其後的命令仍然會被執行,沒有回滾,這也就是:Redis部分支援事務。

小結:

通過WATCH命令在事務執行之前監控了多個Keys,倘若在WATCH之後有任何Key的值發生了變化,EXEC命令執行的事務都將被放棄,同時返回Nullmulti-bulk應答以通知呼叫者事務執行失敗

相關文章