命令 | 格式 | 做用 | 返回結果 |
---|---|---|---|
WATCH | WATCH key [key ...] | 將給出的Keys 標記爲監測態 ,做爲事務執行的條件 |
always OK. |
UNWATCH | UNWATCH | 清除事務中Keys 的 監測態 ,若是調用了EXEC or DISCARD,則沒有必要再手動調用UNWATCH |
always OK. |
MULTI | MULTI | 顯式 開啓redis事務 ,後續commands 將排隊,等候使用EXEC進行原子執行 |
always OK. |
EXEC | EXEC | 執行事務中的commands 隊列,恢復鏈接狀態。若是WATCH在以前被調用,只有監測 中的Keys 沒有被修改,命令纔會被執行,不然中止執行(詳見下文,CAS機制 ) |
成功: 返回數組 —— 每一個元素對應着原子事務中一個 command 的返回結果;失敗: 返回 NULL (Ruby 返回`nil` ); |
DISCARD | DISCARD | 清除事務中的commands 隊列,恢復鏈接狀態。若是WATCH在以前被調用,釋放 監測 中的Keys |
always OK. |
注意:程序員
------
MULTI
,EXEC
,DISCARD
纔是顯式
開啓並控制事務的經常使用命令,可類比關係型數據庫
中的BEGAIN
,COMMIT
,ROLLBACK
(事實上,差距很大);redis
------
WATCH
命令的使用是爲了解決事務併發
產生的不可重複讀
和幻讀
的問題(簡單理解爲給Key加鎖
);數據庫
MULTI, EXEC, DISCARD and WATCH 是Redis事務的基礎。用來顯式開啓並控制一個事務,它們容許在一個步驟中執行一組命令
。並提供兩個重要的保證:編程
命令隊列
做爲一個單獨的原子操做被執行。commands
;commands
都被執行。同時,redis使用AOF(append-only file),使用一個額外的write操做
將事務寫入磁盤。若是發生宕機,進程奔潰等狀況,可使用redis-check-aof tool 修復append-only file,使服務正常啓動,並恢復部分操做。數組
使用MULTI
命令顯式開啓
Redis事務。 該命令老是以OK迴應。此時用戶能夠發出多個命令,Redis不會執行這些命令,而是將它們排隊
。EXEC
被調用後,全部的命令都會被執行。而調用DISCARD
能夠清除
事務中的commands隊列
並退出事務
。bash
>MULTI
OK
>INCR foo
QUEUED
>INCR bar
QUEUED
>EXEC
1)(整數)1
2)(整數)1
複製代碼
從上面的命令執行中能夠看出,EXEC
返回一個數組
,其中每一個元素都是事務中單個命令的返回結果,並且順序與命令的發出順序相同
。 當Redis鏈接處於MULTI
請求的上下文中時,全部命令將以字符串QUEUED
(從Redis協議的角度做爲狀態回覆發送)做爲回覆,並在命令隊列
中排隊。只有EXEC被調用時,排隊的命令纔會被執行,此時纔會有真正的返回結果
。服務器
事務期間,可能會遇到兩種命令錯誤:併發
EXEC
命令以前出現錯誤(COMMAND
排隊失敗)。語法錯誤
(參數數量錯誤,錯誤的命令名稱...);某些關鍵條件
,如內存不足的狀況(若是服務器使用maxmemory
指令作了內存限制
)。客戶端會在EXEC
調用以前檢測第一種錯誤。 經過檢查排隊命令的狀態回覆
(***注意:這裏是指排隊
的狀態回覆
,而不是執行結果
***),若是命令使用QUEUED
進行響應,則它已正確排隊,不然Redis將返回錯誤。若是排隊命令時發生錯誤,大多數客戶端將停止該事務並清除命令隊列
。然而:app
Redis 2.6.5以前
,這種狀況下,在EXEC
命令調用後,客戶端會執行命令的子集(成功排隊的命令)而忽略以前的錯誤。Redis 2.6.5開始
,服務端會記住在累積命令期間發生的錯誤,當EXEC
命令調用時,將拒絕執行事務,並返回這些錯誤,同時自動清除命令隊列
。>MULTI
+OK
>INCR a b c
-ERR wrong number of arguments for 'incr' command
複製代碼
這是因爲
INCR
命令的語法錯誤,將在調用EXEC
以前被檢測出來,並終止事務(version2.6.5+)。ui
EXEC
命令以後出現錯誤。錯誤的值
對某個key
執行操做(如針對String
值調用List
操做)EXEC
命令執行以後發生的錯誤並不會被特殊對待:即便事務中的某些命令執行失敗,其餘命令仍會被正常執行
。
>MULTI
+OK
>SET a 3
+QUEUED
>LPOP a
+QUEUED
>EXEC
*2
+OK
-ERR Operation against a key holding the wrong kind of value
複製代碼
EXEC
返回一個包含兩個元素的字符串數組,一個元素是OK
,另外一個是-ERR……
。- 可否將錯誤合理的反饋給用戶這取決於
客戶端library
(如:Spring-data-redis.redisTemplate
)的自身實現。- 須要注意的是,即便命令失敗,隊列中的全部其餘命令也會被處理----Redis不會中止命令的處理。
重點
)事實上Redis命令
在事務執行時可能會失敗,但仍會繼續執行剩餘命令
而不是Rollback
(事務回滾)。若是你使用過關係數據庫
,這種狀況可能會讓你感到很奇怪。然而針對這種狀況具有很好的解釋:
Redis命令
可能會執行失敗,僅僅是因爲錯誤的語法被調用(命令排隊時檢測不出來的錯誤),或者使用錯誤的數據類型操做某個Key
: 這意味着,實際上失敗的命令都是編程錯誤形成的,都是開發中可以被檢測出來的,生產環境中不該該存在。(這番話,完全甩鍋,「都是大家本身編程錯誤,與咱們無關」。)Rollback
,Redis
內部簡潔而且更加高效。「若是錯誤就是發生了呢?」這是一個反對Redis
觀點的爭論
。然而應該指出的是,一般狀況下,回滾並不能挽救編程錯誤。鑑於沒有人可以挽救程序員的錯誤,而且Redis命令
失敗所需的錯誤類型不太可能進入生產環境,因此咱們選擇了不支持錯誤回滾(Rollback)這種更簡單快捷的方法。
DISCARD
被用來停止事務。事務中的全部命令將不會被執行,鏈接將恢復正常狀態。
> SET foo 1
OK
> MULTI
OK
> INCR foo
QUEUED
> DISCARD
OK
> GET foo
"1"
複製代碼