Redis 中的事務

2022-01-10 03:53:35 字數 2448 閱讀 6141

稍微了解 redis 的朋友都知道,redis 也提供了事務功能。但是 redis 的事務和我們平時熟悉的關係型資料庫中的事務是有區別的。

redis 事務的本質是一組命令的集合:乙個事務中所有命令都會被序列化到乙個佇列中,在事務執行過程,會按照順序序列執行佇列中的命令,這些命令要麼全部得到執行,要麼全部不執行。另外,其他客戶端提交的命令請求不會插入到事務執行命令序列中。

redis 事務的基礎是multiexecdiscardwatch等命令。

這些命令的使用方式如下:

# 開啟事務

multi

command1

command2

# 觸發事務

exec

multi命令用於開啟乙個事務,它總是返回okmulti執行之後, 客戶端可以繼續向伺服器傳送任意多條命令, 這些命令不會立即被執行, 而是被放到乙個佇列中。

exec命令負責觸發並執行事務中的所有命令,exec命令的回覆是乙個陣列, 陣列中的每個元素都是執行事務中的命令所產生的回覆。 其中, 回覆元素的先後順序和命令傳送的先後順序一致。

當使用 aof 方式做持久化的時候, redis 會令將事務寫入到磁碟中。 然而,如果 redis 伺服器因為某些原因被管理員殺死,或者遇上某種硬體故障,那麼可能只有部分事務命令會被成功寫入到磁碟中。redis 在重新啟動時發現 aof 檔案出了這樣的問題,那麼它會退出,並匯報乙個錯誤。 使用redis-check-aof程式可以修復這一問題:它會移除 aof 檔案中不完整事務的資訊,確保伺服器可以順利啟動。

另外,需要注意的是:如果客戶端在使用 multi 開啟了乙個事務之後,卻因為斷線而沒有成功執行 exec ,那麼事務中的所有命令都不會被執行。

使用事務時可能會遇上以下兩種錯誤:

對於在執行 exec 之前發生的錯誤,伺服器會對命令入隊失敗的情況進行記錄,並在客戶端呼叫 exec 命令時,拒絕執行並自動放棄這個事務。

至於那些在 exec 命令執行之後所產生的錯誤, 並沒有對它們進行特別處理: 即使事務中有某個/某些命令在執行時產生了錯誤, 事務中的其他命令仍然會繼續執行。

對於第二種情況,敏感的朋友會問:redis 發現錯誤時會不會回滾已經執行成功的操作呢?答案是不會。

redis 給出的理由是:

如果我們的程式中確實需要對事務進行回滾,可以結合使用 lua 指令碼來實現事務。簡單的做法是在事務開始前記錄狀態,如果在程式執行過程中發生了異常錯誤,將被修改的資料恢復到之前即可。

watch 命令可以為 redis 事務提供 check-and-set (cas)行為。

被 watch 的鍵會被監視,並會發覺這些鍵是否被改動過了。 如果有至少乙個被監視的鍵在 exec 執行之前被修改了, 那麼整個事務都會被取消, exec 返回空來表示事務已經失敗。

當發生被監控的鍵被改變時,程式需要做的就是不斷重試這個操作, 直到沒有發生碰撞為止。

下面我們來演示下watch命令的使用:

127.0.0.1:6379> set csx:key:1 test

ok127.0.0.1:6379> watch csx:key:1

ok127.0.0.1:6379> multi

ok127.0.0.1:6379> ping message1

queued

127.0.0.1:6379> ping message2

queued

# 在執行 exec 之前,使用另外乙個客戶端將csx:key:1這個鍵的值修改了

127.0.0.1:6379> exec

(nil)

watch 使得 exec 命令需要有條件地執行: 事務只能在所有被監視鍵都沒有被修改的前提下執行, 如果這個前提不能滿足的話,事務就不會被執行。

如果你使用 watch 監視了乙個帶過期時間的鍵, 那麼即使這個鍵過期了, 事務仍然可以正常執行。

當 exec 被呼叫時, 不管事務是否成功執行, 對所有鍵的監視都會被取消。另外, 當客戶端斷開連線時, 該客戶端對鍵的監視也會被取消。

使用無引數的 unwatch 命令可以手動取消對所有鍵的監視。 對於一些需要改動多個鍵的事務, 有時候程式需要同時對多個鍵進行加鎖, 然後檢查這些鍵的當前值是否符合程式的要求。 當值達不到要求時, 就可以使用 unwatch 命令來取消目前對鍵的監視, 中途放棄這個事務, 並等待事務的下次嘗試。

當 redis 客戶端開啟了事務,並且也輸入了幾個命名,但是客戶端因為某些原因斷開了。那麼 redis 服務端是怎麼處理那些已經進入佇列的命令的?

Redis中的事務

flushall清除所有的鍵值 1 multi 開啟事務,事務塊中的多條語句會按照順序放入佇列中。multi incr counter1 incr counter2 incr counter3 ping get counter1 2 exec 執行事務塊中的命令 3 watch 監視乙個或者多個ke...

redis中的事務

redis支援簡單的事務 redis與 mysql事務的對比 mysql redis 開啟 start transaction muitl 語句 普通sql 普通命令 失敗 rollback 回滾 discard 取消 成功 commit exec 注 rollback與discard 的區別 如果...

Redis 中的事務

redis支援簡單的事務 redis與 mysql 事務的對比 mysql redis 開啟start transaction muitl 語句普通sql 普通命令 失敗rollback 回滾 discard 取消 成功commit exec 注 rollback 與discard 的區別如果已經成...