前兩篇 Redis 文章都大幾千字,今天咱們換個小清新點的,篇幅很少也容易理解。redis
若是你也瞭解過關係型數據庫事務的話,相信這篇文章對你來講是很容易理解的了。具體什麼是事務我就不說很少了,直接講 Redis 事務相關的部分。數據庫
首先,咱們先來看下,Redis 是怎麼執行事務的。編程
show code:設計模式
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set a test1
QUEUED
127.0.0.1:6379> set b test2
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
127.0.0.1:6379> get a
"test1"
127.0.0.1:6379> get b
"test2"
複製代碼
一個事務的開始到結束會通過如下 3 個過程bash
結合上面的例子,用人話介紹這 3 個過程就是:微信
Redis 執行 multi 命令標誌事務開始。數據結構
當客戶端切換至事務狀態後,服務端會將除了 exec、discard(取消事務,放棄執行事務塊內的全部命令)、watch 和 multi 之外的命令放進一個先進先出的事務隊列中。即上面例子的 2 個 set 命令會被放進隊列,並返回 QUEUED 給客戶端。架構
當客戶端發送 exec 命令時,服務端會當即執行該命令。遍歷這個客戶端的事務隊列,執行隊列保存的全部命令。最後將執行命令所得結果返回給客戶端。ui
二者最大區別就是 Redis 事務不支持回滾。即便事務隊列中某個命令在執行期間發生了錯誤,事務也會繼續執行,直到事務隊列中全部命令執行完成。spa
文字貌似不夠直觀,沒事,看下面的例子你就立刻明白了。
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set msg test
QUEUED
127.0.0.1:6379> lpop msg
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> get msg
"test" // 不受後面錯誤命令影響
複製代碼
PS:若是客戶端向事務入列一個錯誤的命令(好比輸入一個不存在的命令,像:sett 命令),那麼該事務將不被服務端執行。該狀況是入隊錯誤,上面例子是執行錯誤的狀況。
提到 redis 事務,就不得不提 watch 命令了。
該命令是一個樂觀鎖,只能在客戶端進入事務狀態以前執行。
做用是 exec 命令執行以前,監視任何數量個鍵,並在 exec 命令執行時,檢查被監視的鍵是否至少有一個已經被修改過。如果則拒絕執行事務,不然執行。
當 exec 執行完成後,此次事務也就結束了。
咱們依舊來看一個簡單的栗子:
127.0.0.1:6379> SET msg test //設置 msg 的值
OK
127.0.0.1:6379> WATCH msg //監視 msg
OK
127.0.0.1:6379> SET msg test2 //修改 msg 的值(或其餘客戶端在該客戶端執行 exec 命令以前修改該值)
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET msg test3
QUEUED
127.0.0.1:6379> GET msg
QUEUED
127.0.0.1:6379> EXEC
(nil) //執行失敗
複製代碼
PS:本文原創發佈於微信公衆號「不僅Java」,堅持原創!後臺回覆如下關鍵字獲取經典必讀書籍:Java、MySQL、Redis、Linux、mq、數據結構、設計模式、編程思想、架構