redis點滴 事務(二)

redis事務 

multi exec discard 和watch 是redis事務的基礎

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

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

 2.事務是一個原子操作:事務中的命令要麼全部地執行,要麼全部都不執行

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

  1.如果客戶端在使用multi 開啓一個事務之後,卻因爲斷線而沒有成功執行EXEC,那麼事務中所有命令都不會執行

  2.另一方面,如果客戶端成功在開啓事務之後執行EXEC,那麼事務中所有命令都會執行

  例如 購票過程,

  ticket-1 ,mobey-100

 而票只有一張,如果在multi之後,跟EXEC之前,被別人買了,所以ticket爲0

  那我該如何監視這種情景,並不提交

  悲觀的想法:覺得所有的人都在跟我搶這個ticket,此時給ticket上鎖,只有我能操作【悲觀鎖】

  樂觀的想法:我只需要注意這個ticket的值就可以了【樂觀鎖】

 redis的事務中就是開啓了樂觀鎖,只負責監聽ticket有沒有被改動

 用法

multi 命令用戶開啓一個事務,它總是返回ok

multi 執行之後,客戶端可以繼續向服務端發送任意多條命令,這些命令不會立即執行,而是被放到一個隊列中,當需要調用時,所有隊列中的命令纔會被執行

另一方面,通過調用discard,客戶端會清除事務隊列,並放棄執行事務

以下是一個事務例子, 它原子地增加了 foo 和 bar 兩個鍵的值:

> MULTI
OK

> INCR foo
QUEUED

> INCR bar
QUEUED

> EXEC
1) (integer) 1
2) (integer) 1

EXEC 命令的回覆是一個數組, 數組中的每個元素都是執行事務中的命令所產生的回覆。 其中, 回覆元素的先後順序和命令發送的先後順序一致。

當客戶端處於事務狀態時, 所有傳入的命令都會返回一個內容爲 QUEUED 的狀態回覆(status reply), 這些被入隊的命令將在 EXEC命令被調用時執行。


事務中的錯誤

使用事務可能會用到下面2種錯誤

 1.事務在執行exec之前,入列的命令可能會有錯,如果說,命令語法錯誤

  2.命令在調用exec調用之後失敗。比如事務命令可能處理了錯誤類型的鍵,把列表命令的鍵放到string中

 對於發生在exec執行之前的錯誤,客戶端的做法是檢查命令入列得到的值,如果命令是queue,則入列成功,否則,入列失敗,如果入列失敗,則大部分事務都會停止並取消這個事務

 對於發生在exec執行之後的錯誤,並沒有對他們進行特別處理:即使事務中某個/某些事務發生錯誤,而其它的命令仍然會繼續執行

 

爲什麼Redis不支持回滾

如果你有使用關係式數據的經驗,那麼“redis在事務失敗時不進行回滾,而是繼續執行餘下的命令”這種做法可能會讓你覺得有點奇怪

以下是這種做法的優點:

  1.Redis命令只會因爲錯誤的語法而失敗(並且這些問題不能在入隊時發現),或是命令用在了錯誤類型的鍵上面:也就是說,從實用性的角度來說,失敗的命令是由編程錯誤造成的,而這些錯誤應該在開發的過程中被發現,而不應該出現在生產環境中

  2.因爲不需要對回滾進行支持,所以Redis的內部保存簡單且快速


放棄事務

當執行discard命令時,事務會被放棄,並且客戶端會從事務狀態中退出


使用check-and-set操作實現樂觀鎖

watch命令可以爲redis事務提供check-and-set(cas)行爲

被watch的鍵會被監視,並會發覺這些鍵是否被改動。如果至少一個被監視的鍵在exec執行之前被修改了,那麼整個事務都會被取消,exec返回空多條批量回復來表示事務已經失效

舉個例子,假設客戶端有A和B 2個都讀取了鍵原來的值,比如10,執行incr操作的時候,那麼2個客戶端都會將鍵的值設爲11,但正確返回結果應該是12纔對

有了watch,我們就可以輕鬆地解決這類問題了:

watch mykey

val=get mykey

val=val+1

multi

set mykey $val

exec

使用上面的代碼,如果有了watch之後,exec執行之前,有其他客戶端修改了mykey的值,那麼當前客戶端的事務就會失效。程序需要做的,就是不斷重試這個操作,知道沒有發生碰撞爲止

這種形式的鎖被稱爲樂觀鎖,它是非常強大的鎖機制。並且因爲大多數情況下,不同的客戶端會訪問不同的值,碰撞的情況一般都很少,所以通常並不需要重試













發佈了81 篇原創文章 · 獲贊 91 · 訪問量 40萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章