一、概述
和傳統關系型數據庫一樣,Redis 同樣是支持事務的。Redis 的事務可以通過 MULTI/EXEC/DISCARD/WATCH 等命令來實現。
二、事務的 ACID 特性
1). 原子性:事務中的命令要么全部執行,要么都不執行。
Redis 的事務和傳統的關系型數據庫事務最大的區別在于:Redis 事務不支持回滾,即使事務隊列中某個命令執行期間出現了錯誤,整個事務也會繼續執行下去,知道事務隊列中所有命令執行完畢。
那么不支持回滾對 Redis 來說有何優勢:不需要支持回滾,Redis 內部可以保證簡單而快速。
不支持回滾是否合理:合理,事務隊列中的命令在執行過程中,只會因為命令錯誤的語法而失敗,而失敗的命令是編程造成的,這些錯誤應該在開發過程中被發現,而不應該出現在生產環境中。
2). 一致性:數據庫在事務執行之前是一致的,在事務執行后無論事務執行成功還是失敗,數據庫都應該是一致的。
“一致” 指的是數據符合數據庫本身的定義和要求,沒有非法或者無效的錯誤數據。Redis 通過謹慎的錯誤檢測和簡單的設計保證事務的一致性(詳看本頁:四)
3). 隔離性:各個事務之間不會相互影響,在并發狀態下和在串行狀態下執行事務的結果完全相同。
4). 持久性:當事務執行完畢后,結果保存到數據庫中不會丟失。
- 無持久化機制下,事務部具有持久性:服務器停機重啟后數據丟失。
- RDB 機制下,在特定條件下才會保存數據集快照,不能保證數據在第一時間被保存在硬盤中。
- AOF 機制下,appendfsync = always 時,程序總會在執行命令之后調用同步函數,將命令數據存在硬盤中,這種情況下的事務具有持久性。
- AOF 機制下,appendfsync = everysec 時候,程序會每秒同步一次數據到硬盤。因為停機可能就發生在命令執行完畢但是尚未同步的那一秒鐘內,這樣會造成事務數據丟失,故而不具有持久性。
- AOF 機制下,appendfsync = no,由操作系統決定何時將數據同步到硬盤。因為事務數據可能在等待同步的過程中丟失,這樣會造成事務數據丟失,故而不具有持久性。
三、相關命令的用法
1). MULTI 與 EXEC:MULTI 用于開啟事務,總是返回 ok。MULTI 執行后,后面的命令暫時不會執行,而是會存到隊列中,等到 EXEC 執行之后,隊列中的命令才會依次序執行。例子如下:
2). DISCARD 始終返回 ok,會清空事務隊列,并且放棄執行事務。例子如下:
3). WATCH 命令(想看本頁:五)
四、Redis 怎樣處理事務中的錯誤
Redis 怎樣處理事務中的錯誤來保證數據庫的 “一致性” :
1). 入隊錯誤
可能原因:命令不存在,命令格式不正確等
處理方式:Redis 會對入隊失敗的命令進行記錄,當調用 exec 的時候,自動拒絕執行并放棄這個事務。
例子如下:INCR mykey 1 入隊失敗,因為命令格式不正確。
2). 執行錯誤
可能原因:命令語法錯誤(入隊時無法檢測,只有在執行的時候才會報錯,比如事務中處理集合的命令用在了字符串上面)。
處理方式:事務中的命令執行失敗,繼續執行下一條命令,直至事務隊列中的命令執行結束。
例子如下:LPOP mykey 報錯,作用于 list 類型,不能用于字符串;但是不影響后續命令執行,+1 操作依然執行成功。
3). 服務器停機
- 如果服務器運行在無持久化的模式下,那么重啟后的數據庫是空白的,空白的數據庫總是一致的。
- 如果服務器運行在 RDB 模式下,可以利用現有的 RDB 文件還原數據庫到一個一致的狀態。若 RDB 文件找不到,那么重啟后的數據庫是空白的,空白的數據庫總是一致的。
- 如果服務器運行在 AOF 模式下,可以根據現有的 AOF 文件來恢復數據,將數據庫還原到一個一致的狀態。若 AOF 文件找不到,那么重啟后的數據庫是空白的,空白的數據庫總是一致的。
綜上所述,服務器停機不會影響數據庫一致性。
五、WATCH 命令與樂觀鎖
WATCH 命令的返回值總是為 ok。
WATCH 命令本身就是一個樂觀鎖,它可以在 EXEC 命令執行之前,監視一定數量的 key,并在 EXEC 執行時,檢查這些 key 是否被修改過,如果是的話,服務器就拒絕執行事務。例子如下:
時間 | 客戶端A | 客戶端B |
T1 | WATCH name | |
T2 | MULTI | |
T3 | SET name aa | |
T4 | SET name bb | |
T5 | EXEC |
客戶端 A 執行事務的時候發現 name 的值被修改了,所以服務器拒絕執行這個事務。
如何取消對 key 的監視:
- WATCH 對 key 的監視從調用 WATCH 開始生效,直到調用 EXEC 為止。EXEC 被調用的時候不管事務是否執行,都會取消對 key 的監視。
- 另外當客戶端斷開連接后也會取消監視。
- 使用無參數的 UNWATCH 可以取消對所有 key 的監視。
文章列表