聊聊 Redis 的事務

背景

提到事務想必大家一定不會陌生,工作面試中多多少少都會了解到,這篇文章主要帶大家再簡單回憶一下事務的基本知識,然後重點介紹下 Redis 的事務,關於 Redis 的事務有何不同我們繼續往下看就知道了。

什麼事務

說到事務,首先我們需要知道什麼是事務。首先事務是作為單個邏輯工作單元執行的一系列操作,這些操作作為一個整體一起向系統提交,要麼都執行,要麼都不執行。事務是一個不可分割的邏輯單元。

事務的四大特性

  1. A(原子性)事務的各步操作是不可分的,保證一系列的操作要麼都完成,要麼都不完成;
  2. C(一致性)事務完成,數據必須處於一致的狀態;
  3. I(隔離性)對數據進行修改的所有併發事務彼此之間是相互隔離,這表明事務必須是獨立的,不應以任何方式依賴或影響其他事務;
  4. D(持久性)表示事務對數據處理結束後,對數據更改必須持久化,不管是事務成功還是回滾。事務日誌都能夠保持事務的永久性。

以上是常規的事務以及事務的特性。下面我們來看一下什麼是Redis的事務,以及Redis事務有什麼特殊性質。

Redis 事務

關於Redis的性質官方文檔如下

MULTI, EXEC, DISCARD and WATCH are the foundation of transactions in Redis. They allow the execution of a group of commands in a single step, with two important guarantees:

All the commands in a transaction are serialized and executed sequentially.

Either all of the commands or none are processed, so a Redis transaction is also atomic.

意思是說 MULTI,EXEC,DISCARS,WATCH 這四個命令是 Redis 的基石,它們允許在保證下面兩點的條件下單步執行一組命令。

  1. 事務中所有的命令都是都是順序的並且按順序執行;
  2. 要麼處理所有命令,要麼不處理任何命令,因此Redis事務也是原子的

Redis 事務的使用

我們先來看下Redis事務的使用方式,關鍵命令如下Multi,Exec,Discard ,WATCH

使用Multi命令表示開啟一個事務

聊聊 Redis 的事務

開啟一個事務過後中間輸入的所有命令都不會被立即執行,而是被加入到隊列中緩存起來,當收到Exec命令的時候Redis服務會按入隊順序依次執行命令。

聊聊 Redis 的事務

從上面的兩個截圖中我們可以看出以下幾點

  1. multe 命令可以開啟一個事務,開啟成功會 redis 會返回 OK 狀態;
  2. 在multi命令後輸入的命令不會被立即執行,而是被加入的隊列中,並且加入成功 redis 會返回 QUEUED,表示加入隊列成功,如果這裡的命令輸入錯誤了,或者命令參數不對,Redis 會返回 ERR 如下圖,並且此次事務無法繼續執行了。這裡需要注意的是在 Redis 2.6.5 版本後是會取消事務的執行,但是在 2.6.5 之前 Redis 是會執行所有成功加入隊列的命令。詳細信息可以看官方文檔。If there is an error while queueing a command, most clients will abort the transaction discarding it.
  3. 輸入exec命令後會依次執行加入到隊列中的命令

Redis 事務中的錯誤

上面提到了在 Redis 的事務中命令在加入隊列的時候如果出錯,那麼此次事務是會被取消執行的。這種錯誤在執行exec 命令前 Redis 服務就可以探測到,但是在 Redis 事務中還有一種錯誤,那就是所有命令都加入隊列成功,了,但是在執行exec命令的過程中出現了錯誤,這種錯誤 Redis 是無法提前探測到的,那麼這種情況下 Redis 的事務是怎麼處理的呢?

可能到這裡你會說:這還用說,回滾啊,傻子都知道。

但是重點來了,真的是這樣的嗎?下面我們看一個例子,如圖:

聊聊 Redis 的事務

聊聊 Redis 的事務

上面我們測試的過程是我們先通過命令get a獲取a 的值為 5,然後開啟一個事務,在事務中執行兩個動作,第一個是自增a 的值,另一個是通過命令hset a b 3來設置a 中 b 的值,我們可以看到這裡a 的類型是字符串,但是第二個命令也成功的加入到了隊列,Redis 並沒有報錯。但是最後在執行exec 命令的時候,第一條命令執行成功了,看到返回結果是 6,第二條命令執行失敗了,提示的錯誤信息表示類型不對。

然後我們在通過get a命令發現a的值已經被改變了,不再是之前的 5 了,說明雖然事務失敗了但是命令執行的結果並沒有回滾!

看到這裡的小夥伴估計都驚呆了,估計會說我在扯犢子,但是事實就是如此,那麼到底是為什麼會這樣呢?我們看下官方給的解釋。

Redis 為什麼不支持事務回滾

Redis commands can fail only if called with a wrong syntax (and the problem is not detectable during the command queueing), or against keys holding the wrong data type: this means that in practical terms a failing command is the result of a programming errors, and a kind of error that is very likely to be detected during development, and not in production.Redis is internally simplified and faster because it does not need the ability to roll back.

上面總共提到兩點解釋,第一點意思是說在開發環境中就能避免掉語法錯誤或者類型不匹配的情況,在生產上是不會出現的;第二點是說 Redis 的內部是簡單的快速的,所以不需要支持回滾的能力。

從這裡我們可以看出 Redis 的開發者很自信,所以我猜測他們用的洗髮露肯定是海飛絲的。

小結

簡單總結一下,今天剛開始跟大家回顧了一個事務的定義以及事務的四大特性,然後引入 Redis 的事務,並且通過例子給大家演示了 Redis 事務的使用以及特性。另外如果大家覺得感興趣的話可以自己去讀讀官方文檔,加深印象。


分享到:


相關文章: