前兩篇 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 個過程微信
結合上面的例子,用人話介紹這 3 個過程就是:數據結構
Redis 執行 multi 命令標誌事務開始。架構
當客戶端切換至事務狀態後,服務端會將除了 exec、discard(取消事務,放棄執行事務塊內的全部命令)、watch 和 multi 之外的命令放進一個先進先出的事務隊列中。即上面例子的 2 個 set 命令會被放進隊列,並返回 QUEUED 給客戶端。spa
當客戶端發送 exec 命令時,服務端會當即執行該命令。遍歷這個客戶端的事務隊列,執行隊列保存的全部命令。最後將執行命令所得結果返回給客戶端。設計
二者最大區別就是 Redis 事務不支持回滾。即便事務隊列中某個命令在執行期間發生了錯誤,事務也會繼續執行,直到事務隊列中全部命令執行完成。code
文字貌似不夠直觀,沒事,看下面的例子你就立刻明白了。
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、數據結構、設計模式、編程思想、架構