redis官方文檔:Redis transactions
相關命令:
Redis中的事務是一組命令的集合。一個事務中的命令要么都執行,要么都不執行。事務在執行期間,服務器不會中斷事務而去執行其它客戶端的命令請求,它會將事務中的所有命令都執行完,然后才去處理其它客戶端的命令請求。
一、事務的實現
1.multi——開啟事務
通過multi命令開啟事務,它總是返回OK。MULTI執行之后,客戶端可以繼續向服務器發送任意多條命令, 這些命令不會立即被執行,而是被放到一個隊列中
,當 EXEC命令被調用時, 所有隊列中的命令才會被執行。
2.命令入隊列
之后所有的命令都會放入事務隊列中,並不會立刻執行。
如果客戶端發送的命令為EXEC,DISCARD,WATCH,MULTI四個命令中的其中一個,服務器會立刻執行這個命令。
對於這四個命令以外的其它命令,服務器並不會立刻執行,而是將這個命令放入一個事務隊列中,然后向客戶端返回QUEUED回復。
服務器判斷命令是該入隊還是該立即執行的過程可以用以下流程圖來描述。
事務隊列以先進先出(FIFO)的方式保存入隊的命令的。
3.exec——執行事務
當客戶端向服務器發送EXEC命令時,會立刻執行。
服務器會遍歷這個客戶端的事務隊列,執行隊列中保存的所有命令,最后將執行命令所得的結果全部返回給客戶端。
4.DISCARD——放棄執行
當執行 DISCARD 命令時, 事務會被放棄, 事務隊列會被清空,並且客戶端會從事務狀態中退出。
5.錯誤處理
redis的事務沒有關系數據庫事務提供的回滾功能,
①語法錯誤。
命令不存在或者參數的個數不對。
例如,跟在multi命令后執行了4個命令,兩個是正確的命令,會成功入事務隊列,還有兩個命令有語法錯誤。而只要有一個命令有語法錯誤,執行EXEC命令后Redis就會執行返回錯誤,連語法正確的命令也不會執行。
127.0.0.1:6379> multi OK 127.0.0.1:6379> set key 1 QUEUED 127.0.0.1:6379> set key (error) ERR wrong number of arguments for 'set' command 127.0.0.1:6379> errorcommand key (error) ERR unknown command 'errorcommand' 127.0.0.1:6379> set key 2 QUEUED 127.0.0.1:6379> exec (error) EXECABORT Transaction discarded because of previous errors.
②運行錯誤。
執行命令時出現的錯誤,比如使用散列類型的命令操作集合類型的鍵,這種錯誤在實際執行之前redis是無法發現的,所以在事務里這樣的命令是會被redis接受並執行的。
如果事務里的一條命令出現了運行錯誤,其它命令仍然會繼續執行,包括出錯命令之前和之后的命令。
127.0.0.1:6379> multi OK 127.0.0.1:6379> set key 1 QUEUED 127.0.0.1:6379> sadd key 2 QUEUED 127.0.0.1:6379> set key 3 QUEUED 127.0.0.1:6379> exec 1) OK 2) (error) WRONGTYPE Operation against a key holding the wrong kind of value 3) OK 127.0.0.1:6379> get key "3"
開發者必須自己收拾爛攤子,將數據庫恢復到事務執行前的狀態。因此,與關系數據庫的事務相比,redis的事務比較雞肋。
二、watch命令
watch命令是一個樂觀鎖,可以為Redis事務提供 check-and-set (CAS)行為。它可以在EXEC命令執行前監視任意數量的鍵(key),在執行EXEC命令時,檢查被監視的鍵是否已經被修改過,一旦發現被監視的鍵至少有一個被修改,服務器將拒絕執行事務,並向客戶端返回代表事務執行失敗的空回復(nil-reply)。
執行EXEC命令后會取消對所有鍵的監控,如果不想執行事務中的命令可以使用UNWATCH命令來取消監控。