Redis事務命令與原理
本篇部落格是對《Redis設計與實現》相關內容的學習和總結
日期:2020-12-14
Redis版本:3.0.6
事務相關命令
- 開始事務
multi
在執行 multi 命令後,後面執行的非事務相關的命令都會被加入事務佇列,等待事務執行
- 執行事務
exec
執行 multi 和 exec 之間的命令,並統一返回
- 監視鍵
watch key [key ...]
監視一個或多個鍵,如果監視的鍵的值發生了改變,那麼事務將不被執行,並且返回 nil。watch 命令必須在 multi 命令之前執行。
- 取消事務
discard
取消事務,清空事務佇列
實現原理
-
multi 命令
multi
命令時,就會將該客戶端標記為事務狀態。Redis伺服器可以和多個客戶端連線,每個客戶端都有一個對應的客戶端狀態結構來儲存這個客戶端的資訊,包括事務狀態,套接字描述符,輸入輸出緩衝區還有事務佇列等。當進入事務狀態後,這個客戶端發過來的非事務的命令都會加入到事務佇列等待事務執行,而事務相關的命令則會立即執行。 -
exec 命令
當接收到exec
命令時,就會執行事務佇列中的所有命令,因為Redis單執行緒執行命令,所以自然的執行這些命令時,不會穿插其他客戶端的命令。執行完這些命令後,將返回所有命令的執行結果,並且清空事務佇列,清空客戶端對鍵的監視,退出事務狀態。 -
discard 命令
discard
命令時,直接清空事務佇列,清空客戶端對鍵的監視,退出事務狀態。 -
watch 命令
Redis用字典(Redis的字典用雜湊表實現,基本可以將字典看作雜湊表)來儲存監視的鍵和客戶端之間的關係,其中字典的鍵就是被監視的鍵名,字典的值是一個連結串列,每一個節點存有客戶端狀態結構的指標。如下圖所示:
圖一
client-1監視了鍵 "aaa" 和 "ccc",也就是執行了命令watch aaa ccc
,client-2監視了鍵" bbb",也就是執行了命令 watch bbb
,client-3監視了鍵 "ccc",也就是執行了命令 watch ccc
。當一個客戶端執行watch
如果有客戶端對被監視的鍵執行了修改命令,比如對字串型別執行了set
命令,對列表型別執行了lpush
命令等。那麼就會找到監視這個鍵的客戶端列表,對他們做標記(這個標記就在客戶端狀態結構中),他們監視的鍵被修改了。然後等到執行exec
時會做檢查,如果有這個標記就不執行事務直接返回 nil。
當執行了exec
或者discard
命令時,就會清空客戶端對鍵的監視(清空就是清除對所有鍵的監視),也就是將客戶端狀態結構指標從上圖的連結串列中移除,執行unwatch
也可以完成同樣的任務。
Redis事務的特性
- 在執行事務包含的命令時不會穿插其他客戶端的命令
- 在執行命令出錯時,會繼續執行後續命令,沒有回滾功能
參考資料
- 《Redis設計與實現》
- Redis中文文件