Redis事務的使用

一、Redis事務簡介

Redis事務可以一次執行多個命令,一個事務的所有命令都會序列化並按順序地串行化執行,而不會被其他客戶端提交的命令請求插入到事務執行命令序列中。

二、Redis事務命令

下面的表格節選自:https://www.runoob.com/redis/redis-transactions.html

命令 作用
DISCARD 取消事務,放棄執行事務塊內的所有命令
EXEC 執行所有事務塊內的命令
MULTI 標記一個事務塊的開始
UNWATCH 取消WATCH命令對所有key的監視
WATCH key [key …] 監視一個(或多個) key,如果在事務執行之前這個(或這些key)被其他命令所改動,那麼事務將被打斷

三、使用實例

1.MULTI、EXEC

通過MULTI命令開啓一個事務,使用如下:

127.0.0.1:6379> MULTI 
OK

在MULTI命令執行之後,我們可以繼續發送命令去執行,此時的命令不會被立馬執行,而是放在一個隊列中,如下:

127.0.0.1:6379> SET K1 V1
QUEUED
127.0.0.1:6379> SET K2 V2
QUEUED
127.0.0.1:6379> SET K3 V3
QUEUED

當所有的命令都輸入完成後,通過EXEC命令發起執行,如下:

127.0.0.1:6379> EXEC
1) OK
2) OK
3) OK

事務中的三個命令成功執行,如下:

127.0.0.1:6379> KEYS *
1) "K2"
2) "K1"
3) "K3"

2.DISCARD

通過DISCARD命令清空隊列,放棄執行事務塊的所有命令,如下:

127.0.0.1:6379> MULTI 
OK
127.0.0.1:6379> SET K1 111
QUEUED
127.0.0.1:6379> DISCARD
OK
127.0.0.1:6379> GET K1
"V1"

3.WATCH和UNWATCH

事務中的WATCH命令可以用來監控一個或多個key,如果其中至少有一個被WATCH監視的鍵在EXEC執行之前被修改了,那麼整個事務都會被取消,EXEC返回nil來表示事務執行失敗。如下:

127.0.0.1:6379> WATCH K1 K2
OK
127.0.0.1:6379> SET K1 BBB
OK
127.0.0.1:6379> GET K1
"BBB"
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET K1 AAA
QUEUED
127.0.0.1:6379> SET K2 BBB
QUEUED
127.0.0.1:6379> EXEC
(nil)
127.0.0.1:6379> MGET K1 K2
1) "BBB"
2) "V2"

EXEC執行之後之後被監控的所有鍵會自動執行UNWATCH

可以手動通過UNWATCH命令,取消所有鍵的監控,如下:

127.0.0.1:6379> WATCH K1 K2
OK
127.0.0.1:6379> MSET K1 111 K2 222
OK
127.0.0.1:6379> MGET K1 K2
1) "111"
2) "222"
127.0.0.1:6379> UNWATCH
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> MSET K1 AAA K2 BBB
QUEUED
127.0.0.1:6379> EXEC
1) OK
127.0.0.1:6379> MGET K1 K2
1) "AAA"
2) "BBB"

四、事務中的異常

1.進入隊列之前就能發現的錯誤,比如使用錯誤的命令

對於這種錯誤,該命令不進入隊列,Redis服務器也會對命令入隊失敗的情況進行記錄,並在客戶端調用 EXEC 命令時,拒絕執行並自動放棄這個事務。

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SETT K1
(error) ERR unknown command `SETT`, with args beginning with: `K1`, 
127.0.0.1:6379> GET K1
QUEUED
127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.

2.執行EXEC之後才能發現的錯誤,比如對非數字字符進行數學運算;

對於這種情況,Redis並沒有對它們進行特別處理, 即使事務中有某個/某些命令在執行時產生了錯誤, 事務中的其他命令仍然會繼續執行。

127.0.0.1:6379> SET kk vv
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> INCR kk
QUEUED
127.0.0.1:6379> SET K1 V1
QUEUED
127.0.0.1:6379> GET K1
QUEUED
127.0.0.1:6379> EXEC
1) (error) ERR value is not an integer or out of range
2) OK
3) "V1"

從這裏可以看出:
Redis 沒有在事務上增加任何維持原子性的機制,所以 Redis 事務的執行並不是原子性的。

Redis事務可以理解爲一個打包的批量執行腳本,但批量指令並非原子化的操作,中間某條指令的失敗不會導致前面已做指令的回滾,也不會造成後續的指令不做。

官網說明:
Redis 命令只會因爲錯誤的語法而失敗(並且這些問題不能在入隊時發現),或是命令用在了錯誤類型的鍵上面:這也就是說,從實用性的角度來說,失敗的命令是由編程錯誤造成的,而這些錯誤應該在開發的過程中被發現,而不應該出現在生產環境中。因此不需要對回滾進行支持,使得 Redis 的內部可以保持簡單且快速。

五、Redis事務總結

1.事務的三個階段:

  1. 開啓事務——以MULTI命令開啓事務
  2. 命令入隊——接收到的命令不會立即執行,而是加入等待執行的隊列中。
  3. 執行事務——由EXEC命令執行事務,命令實際執行。

2.特性:

  1. 批量的操作命令在客戶端發送 EXEC 命令前被放入隊列緩存。不會被實際執行。
  2. 不保證原子性:收到 EXEC 命令後進入事務執行,事務中任意命令執行失敗,其餘的命令依然被執行。
  3. 單獨的隔離操作:在事務執行過程,事務中的所有命令都會按隊列順序執行,其他客戶端提交的命令請求不會插入到事務執行命令序列中。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章