什么是事務
事務是指一系列操作步驟,這一系列的操作步驟,要么完全地執行,要么完全地不執行。
Redis 中的事務(transaction)是一組命令的集合,至少是兩個或兩個以上的命令,redis 事務保證這些命令被執行時中間不會被任何其他操作打斷。
● multi
語法: multi
作用:標記一個事務的開始。事務內的多條命令會按照先后順序被放進一個隊列當中。返回值:總是返回 ok
● exec
語法:exec
作用:執行所有事務塊內的命令
返回值:事務內的所有執行語句內容,事務被打斷(影響)返回 nil
● discard
語法:discard
作用:取消事務,放棄執行事務塊內的所有命令返回值:總是返回 ok
● watch
語法:watch key [key ...]
作用:監視一個(或多個) key ,如果在事務執行之前這個(或這些) key 被其他命令所改動, 那么事務將被打斷。
返回值:總是返回 ok
● unwatch
語法:unwatch
作用:取消 WATCH 命令對所有 key 的監視。如果在執行 WATCH 命令之后, EXEC 命令或 DISCARD 命令先被執行了的話,那么就不需要再執行 UNWATCH 了
返回值:總是返回 ok
● 正常執行事務
事務的執行步驟: 首先開啟事務, 其次向事務隊列中加入命令,最后執行事務提交
例 1:事務的執行:
1、multi : 用 multi 命令告訴 Redis,接下來要執行的命令你先不要執行,而是把它們暫時存起來 (開啟事務)
2、sadd works john 第一條命令進入等待隊列(命令入隊)
3、sadd works rose 第二條命令進入等待隊列(命令入隊)
4、exce 告知 redis 執行前面發送的兩條命令(提交事務)
查看 works 集合
● 事務執行 exec 之前,入隊命令錯誤(語法錯誤;嚴重錯誤導致服務器不能正常工作(例如內存不足)),放棄事務。
執行事務步驟:
1、MULTI 正常命令
2、SET key value 正常命令
3、INCR 命令語法錯誤
4、EXEC 無法執行事務,那么第一條正確的命令也不會執行,所以 key 的值不會設置成功
結論:事務執行 exec 之前,入隊命令錯誤,事務終止,取消,不執行。
● 事務執行 exec 命令后,執行隊列命令,命令執行錯誤,事務提交
執行步驟:
1、MULTI 正常命令
2、SET username zhangsan 正常命令
3、lpop username 正常命令,語法沒有錯誤,執行命令時才會有錯誤
4、EXEC 正常執行 ,發現錯誤可以在事務提交前放棄事務,執行 discard
結論:在 exec 執行后的所產生的錯誤, 即使事務中有某個/某些命令在執行時產生了錯誤,事務中的其他命令仍然會繼續執行。
Redis 在事務失敗時不進行回滾,而是繼續執行余下的命令。
Redis 這種設計原則是:Redis 命令只會因為錯誤的語法而失敗(這些問題不能在入隊時發現),或是命令用在了錯誤類型的鍵上面,失敗的命令并不是 Redis 導致,而是由編程錯誤造成的,這樣錯誤應該在開發的過程中被發現,生產環境中不應出現語法的錯誤。就是在程序的運行環境中不應該出現語法的錯誤。而 Redis 能夠保證正確的命令一定會被執行。再者不需要對回滾進行支持,所以 Redis 的內部可以保持簡單且快速。
● 放棄事務
執行步驟:
1.MULTI 開啟事務
2.SET age 25 命令入隊
3.SET age 30 命令入隊
4.DISCARD 放棄事務,則命令隊列不會被執行
例 1:
● Redis 的 watch 機制
1、Redis 的 WATCH 機制
WATCH 機制原理:
WATCH 機制:使用 WATCH 監視一個或多個 key , 跟蹤 key 的 value 修改情況, 如果有key 的 value 值在事務 EXEC 執行之前被修改了, 整個事務被取消。EXEC 返回提示信息,表示事務已經失敗
WATCH 機制使的事務 EXEC 變的有條件,事務只有在被 WATCH 的 key 沒有修改的前提下才能執行。不滿足條件,事務被取消。使用 WATCH 監視了一個帶過期時間的鍵, 那么即使這個鍵過期了, 事務仍然可以正常執行
大多數情況下, 不同的客戶端會訪問不同的鍵, 相互同時競爭同一 key 的情況一般都很少, 樂觀鎖能夠以很好的性能解決數據沖突的問題
2、何時取消 key 的監視(WATCH)
① WATCH 命令可以被調用多次。 對鍵的監視從 WATCH 執行之后開始生效, 直到調用 EXEC 為止。不管事務是否成功執行, 對所有鍵的監視都會被取消。
② 當客戶端斷開連接時, 該客戶端對鍵的監視也會被取消。
③ UNWATCH 命令可以手動取消對所有鍵的監視
3、 WATCH 的事例
執行步驟:
首先啟動 redis-server , 在開啟兩個客戶端連接。 分別叫 A 客戶端 和 B 客戶端。
啟動 Redis 服務器
A 客戶端(紅色):WATCH 某個 key ,同時執行事務
B 客戶端(黃色):對 A 客戶端 WATCH 的 key 修改其 value 值。
(1)在 A 客戶端設置 key : str.lp 登錄人數為 10
(2)在 A 客戶端監視 key : str.lp
(3)在 A 客戶端開啟事務 multi
(4)在 A 客戶端修改 str.lp 的值為 11
(5)在 B 客戶端修改 str.lp 的值為 15
(6)在 A 客戶端執行事務 exec
(7)在 A 客戶端查看 str.lp 值,A 客戶端執行的事務沒有提交,因為 WATCH 的 str.lp 的值已經被修改了, 所有放棄事務。
例 1:樂觀鎖