說說 Redis 事務

更多技術文章,請關注我的個人博客 www.immaxfang.com 和小公眾號 Max的學習札記
Redis 事務簡介Redis 只是提供了簡單的事務功能 。其本質是一組命令的集合,事務支持一次執行多個命令,在事務執行過程中,會順序執行隊列中的命令,其他客戶端提交的命令請求不會插入到本事務執行命令序列中 。命令的執行過程是順序執行的,但不能保證原子性 。無法像 MySQL 那樣,有隔離級別 , 出了問題之后還能回滾數據等高級操作 。后面會詳細分析 。
Redis 事務基本指令Redis 提供了如下幾個事務相關的基礎指令 。
  • MULTI開啟事務,Redis 會將后續命令加到隊列中,而不真正執行它們,直到后續使用EXEC來原子化的順序執行這些命令
  • EXEC執行所有事務塊內的命令
  • DISCARD取消事務,放棄執行事務塊內所有的命令
  • WATCH監視一個或多個 key,若事務在執行前,這些 key 被其他命令修改,則事務被終端,不會執行事務中的任何命令
  • UNWATCH取消 WATCH命令對所有 keys 的監視
一般情況下,一個簡單的 Redis 事務主要分為如下幾個部分:
  1. 執行命令MULTI開啟一個事務 。
  2. 開啟事務之后,執行命令的多個命令會依次被放入一個隊列,放入成功則會返回QUEUED消息 。
  3. 執行命令EXEC提交事務,Redis 會依次執行隊列中的命令,并依次返回所有命令的結果 。(若想放棄提交事務,則執行DISCARD) 。
下圖簡單介紹了下 Redis 事務執行的過程:
說說 Redis 事務

文章插圖
實例分析下面我們來通過一些實際具體例子,來體會下 Redis 中的事務 。前面我們也說到 Redis 的事務不是正真的事務,是無法完全滿足標準事務的ACID特性的 。通過下面的例子,我們來看看,Redis 的“破產版”事務到底存在什么問題 。
  • [A]正常執行提交
【說說 Redis 事務】127.0.0.1:6379> MULTIOK127.0.0.1:6379> SET a 1QUEUED127.0.0.1:6379> SET b 2QUEUED127.0.0.1:6379> EXEC1) OK2) OK127.0.0.1:6379> GET a"1"127.0.0.1:6379> GET b"2"開啟事務后,提交的命令都會加入隊列(QUEUED),執行 EXEC 后會逐步執行命令并返回結果 。這個看起來是不是和我們平時使用 MySQL 的事務操作相似,類似 start transaction 和 commit 。
  • [B]正常取消事務
127.0.0.1:6379> MULTIOK127.0.0.1:6379> SET a 1QUEUED127.0.0.1:6379> SET b 2QUEUED127.0.0.1:6379> DISCARDOK127.0.0.1:6379>127.0.0.1:6379> GET a(nil)127.0.0.1:6379> GET b(nil)開啟事務后,若不想繼續事務 , 使用 DISCARD 取消,前面提交的命令并不會真正執行,相關的 key 值不變 。這個看起來也和 MySQL 的事務相似,類似 start transaction 和 rollback 。
  • [C]WATCH 監視 key
-- 線程 1 中執行127.0.0.1:6379> del a(integer) 1127.0.0.1:6379> get a(nil)127.0.0.1:6379> SET a 0OK127.0.0.1:6379> WATCH aOK127.0.0.1:6379> MULTIOK127.0.0.1:6379> SET a 1QUEUED----------------------------------------- 線程 2 中執行----------------------------------------- 127.0.0.1:6379> SET a 2----------------------------------------- OK127.0.0.1:6379> EXEC(nil)127.0.0.1:6379> GET a"2"在開啟事務之前 WATCH 了 a 的值,隨后再開啟事務 。在另一個線程中設置了 a 的值(SET a 2),然后再 EXEC 執行事務,結果為 nil,說明事務沒有被執行 。因為 a 的值在 WATCH 之后發生了變化,所以事務被取消了 。
需要注意的是,這里和開啟事務的時間點沒有關系,與 MULTI 和另一個線程設置 a 的值的先后沒有關系 。只要是在 WATCH 之后發生了變化 。無論事務是否已經開啟,執行事務(EXEC)的時候都會取消 。普通情況下,在執行 EXEC 和 DISCARD 命令時,都會默認執行 UNWATCH 。

推薦閱讀