Redis-事務
阿新 • • 發佈:2020-10-14
1.1 為什麼要用事務
我們知道 Redis 的單個命令是原子性的(比如 get set mget mset),如果涉及到多個命令的時候,需要把多個命令作為一個不可分割的處理序列,就需要用到事務。 例如我們之前說的用 setnx 實現分散式鎖,我們先 set,然後設定對 key 設定 expire,防止 del 發生異常的時候鎖不會被釋放,業務處理完了以後再 del,這三個動作我們就希 望它們作為一組命令執行。 Redis 的事務有兩個特點: 1、按進入佇列的順序執行。 2、不會受到其他客戶端的請求的影響。 Redis 的事務涉及到四個命令: multi(開啟事務),exec(執行事務),discard(取消事務),watch(監視)。1.2 事務的用法
127.0.0.1:6379> set tom 1000 OK 127.0.0.1:6379> set mic 1000 OK 127.0.0.1:6379> multi OK 127.0.0.1:6379> decrby tom 100 QUEUED 127.0.0.1:6379> incrby mic 100 QUEUED 127.0.0.1:6379> exec 1) (integer) 900 2) (integer) 1100 127.0.0.1:6379> get tom
"900" 127.0.0.1:6379> get mic
"1100"
multi set k1 1 set k2 2 set k3 3 discard
1.3 watch 命令
在 Redis 中還提供了一個 watch 命令。它可以為 Redis 事務提供 CAS 樂觀鎖行為(Check and Set / Compare andSwap),也就是多個執行緒更新變數的時候, 會跟原值做比較,只有它沒有被其他執行緒修改的情況下,才更新成新的值。 我們可以用 watch 監視一個或者多個 key,如果開啟事務之後,至少有一個被監視key 鍵在 exec 執行之前被修改了, 那麼整個事務都會被取消(key 提前過期除外)。 可以用 unwatch 取消。1.4 事務可能遇到的問題
1.4.1 在執行 exec 之前發生錯誤
比如:入隊的命令存在語法錯誤,包括引數數量,引數名等等(編譯器錯誤)。127.0.0.1:6379> multi OK 127.0.0.1:6379> set gupao 666 QUEUED 127.0.0.1:6379> hset qingshan 2673 (error) ERR wrong number of arguments for 'hset' command 127.0.0.1:6379> exec (error) EXECABORT Transaction discarded because在這種情況下事務會被拒絕執行,也就是佇列中所有的命令都不會得到執行。
1.4.2 在執行 exec 之後發生錯誤
比如,型別錯誤,比如對 String 使用了 Hash 的命令,這是一種執行時錯誤。127.0.0.1:6379> multi OK 127.0.0.1:6379> set k1 1 QUEUED 127.0.0.1:6379> hset k1 a b QUEUED 127.0.0.1:6379> exec 1) OK 2) (error) WRONGTYPE Operation against a key holding the wrong kind of value 127.0.0.1:6379> get k1 "1"最後我們發現 set k1 1 的命令是成功的,也就是在這種發生了執行時異常的情況下,只有錯誤的命令沒有被執行,但是其他命令沒有受到影響。 這個顯然不符合我們對原子性的定義,也就是我們沒辦法用 Redis 的這種事務機制來實現原子性,保證資料的一致。