Redis高級篇
-
事務
MULTI, EXEC, DISCARD and WATCH命令用於保證Redis中的事務處理
一個事務中的所有命令被序列化並串行執行。
事務的原子性。
用法
MULTI 進入一個事務,這個命令響應“OK”。
EXEC開始執行事務中的命令。
DISCARD將退出事務。
> MULTI
OK
> INCR foo
QUEUED
> INCR bar
QUEUED
> EXEC
1) (integer) 1
2) (integer) 1
事務錯誤處理
事務執行可能出現兩種錯誤:
- 在EXEC執行前,命令不能正常添加到Queue中。例如,命令出現語法錯誤等。
- 在EXEC執行后,例如在string類型上進行list操作。
針對於第一種錯誤,Client通常能看到,在執行命令后響應為“QUEUED”說明成功,否則失敗。
為什么Redis不支持事務回滾
如果你有使用過關系式數據庫的經驗,那么“Redis 在事務失敗時不進行回滾,而是繼續執行余下的命令”這種做法可能會讓你覺得有點奇怪 。
原因如下:
- Redis 命令只會因為錯誤的語法而失敗(這些問題不能在入隊時發現),或是命令用在了錯誤類型的鍵上面:這也就是說,從實用性的角度來說,失敗的命令是由編程錯誤造成的,而這些錯誤應該在開發的過程中被發現,而不應該出現在生產環境中。
- 因為不需要對回滾進行支持,所以 Redis 的內部可以保持簡單且快速。
有種觀點認為 Redis 處理事務的做法會產生 bug ,然而需要注意的是,在通常情況下,回滾並不能解決編程錯誤帶來的問題。舉個例子,如果你本來想通過INCR 命令將鍵的值加上 1 ,卻不小心加上了 2 ,又或者對錯誤類型的鍵執行了INCR,回滾是沒有辦法處理這些情況的鑒於沒有任何機制能避免程序員自己造成的錯誤,並且這類錯誤通常不會在生產環境中出現,所以 Redis 選擇了更簡單、更快速的無回滾方式來處理事務
Discarding the command queue
DISCARD用來中止事務。
> SET foo 1
OK
> MULTI
OK
> INCR foo
QUEUED
> DISCARD
OK
> GET foo
"1"
用check-and-set(CAS)優化鎖
WATCH命令用來監控更新事務的狀態。。
WATCH 關鍵字用來監控為了keys的變化。在EXEC執行前,如果監控中的任一key發生變化,那么事務將會停止,並且EXEC將返回空表示事務失敗。例如,我們需要使key自增1(假設Redis沒有INCR),做法如下:
val = GET mykey
val = val + 1
SET mykey $val
這種做法對於單個client沒有問題,可是對於多個client同時進行操作的話,那么就有問題了。通過WATCH命令我們就能很好地解決這個問題:
WATCH mykey
val = GET mykey
val = val + 1
MULTI
SET mykey $val
EXEC
上面的代碼中,如果其它client修改了WATCH和EXEC之間的變量val,那么事務將會失敗。
WATCH
WATCH可理解為有條件的EXEC命令,也就是說如果要執行事務,那么必須是WATCHed的keys都沒有被其它client修改過,否則事務不執行。
WATCH能被多次調用。
使用UNWATCH(無參數)命令移除不需要監控的keys。
使用WATCH實現ZPOP命令(原子型操作:從集合中移除score最低的元素)的功能
WATCH zset
element = ZRANGE zset 0 0
MULTI
ZREM zset element
EXEC
