Redis中的事務處理機制分析與總結

奕鵬發表於2021-01-18

事務的定義

事務是一組具備原子性操作的命令集合。在這一組命令中,要麼全部執行成功,要麼全部執行失敗。

事務的特點

  1. 原子性。原子性指的是事務操作具備原子操作,一個事務裡面的 SQL 操作要麼全部成功要麼全部失敗,不能存在一些 SQL 成功,一些 SQL 執行失敗。
  2. 隔離性。隔離性指的是多個事務之間是相互隔離的,事務之間是互不受影響的。
  3. 永續性。永續性指的是事務一旦提交,就不能進行回滾(撤回),永久的儲存在磁碟中。
  4. 一致性。一致性指的是事務操作前後必須滿足業務約束。

有關事務的四大特性的具體講解可以參考該文章
mindoc.qqdeveloper.com/docs/mysql/m...

Redis事務執行邏輯

Redis在事務中的命令是新增到一個命令佇列裡面,等待事務提交之後,則一一執行命令佇列裡面的命令。

Redis事務命令

  1. multi:開啟事務。
  2. exec:提交當前事務。
  3. discard:取消當前事務。
  4. watch:監聽key是否在事務開啟之前被其他命令修改,如果被修改去不處理事務內的操作。
  5. unwatch:取消監聽key是否在事務開啟之前被其他的命令修改。

命令演示

  1. 事務執行流程。

客戶端一:負責開啟事務並寫入快取資料。

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set user:id:1 1
QUEUED
127.0.0.1:6379> exec
1) OK

事務執行exec命令返回的是,事務中執行的命令數量以及對應的結果。

客戶端二:負責讀取快取中的資料。

# 客戶端一執行set之後,執行exec之前。
127.0.0.1:6379> get user:id:1
(nil)
# 客戶端執行exec之後。
127.0.0.1:6379> get user:id:1
"1"
  1. watch對key監聽。

客戶端一:負責開啟事務,並使用watch監聽key。

# 監聽key之前檢視值
127.0.0.1:6379> get age
"1"
# 開啟監聽
127.0.0.1:6379> watch age
OK
# 開啟事務
127.0.0.1:6379> multi
OK
# 修改被監聽的key值
127.0.0.1:6379> set age 2
QUEUED
# 提交事務(發現返回的是nil,表示未執行成功。)
127.0.0.1:6379> exec
(nil)
# 重新獲取監聽的key值
127.0.0.1:6379> get age
"3"

客戶端二:負責修改客戶端一中監聽的key。

# 在客戶端一執行watch命令,開啟事務之後,提交事務之前執行。
127.0.0.1:6379> set age 3
OK
# 在客戶端一執行exec命令之後執行。
127.0.0.1:6379> get age
"3"

通過2中的演示,你會發現在事務開啟之前對key做了監聽。事務正常提交之後,被監聽的key在事務中執行的命令是不會被執行的。unwatch對監聽的key,取消監聽事件。此時的取消監聽不能放在事務中,只能在事務開啟之前對key的監聽事件做取消。 事務命令異常處理

事務原子性演示

  1. 命令錯誤的原子性。
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set user:name zhangsan
QUEUED
127.0.0.1:6379> set user:age 1
QUEUED
127.0.0.1:6379> set user:sex max
QUEUED
# 執行一條命令錯誤的操作
127.0.0.1:6379> set a
(error) ERR wrong number of arguments for 'set' command
# 提交事務
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> keys *
1) "user:id:1"
2) "name"
3) "age"

通過上面的演示,在事務中執行一條錯誤的語法命令,整個事務都將不會被執行。

  1. 內部語法使用錯誤。
127.0.0.1:6379> get name
"zhangsan"
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set mu:id 1
QUEUED
# 執行一個語法不當的操作
127.0.0.1:6379> incr name
QUEUED
127.0.0.1:6379> set mu:age 2
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK

通過上面的演示,在事務中執行了一條語法不當的的操作,最終提交事務後。事務中的正確命令依舊不被執行了。這不符合事務原子性的特點。

  1. 事務原子性總結。

    a. 當事務中存在語法使用不當的情況時,事務會跳過當前的命令。其他的正確命令依舊被執行。

    b. Redis中的事務並非一定滿足原子性的特點。

    c. 在事務中,執行的命令,Redis只會檢測是否是一個合法的命令。如果合法則新增到命令佇列,如果不合法則直接阻止整個事務的執行。

常見問題總結

MySQL中的事務與Redis事務的區別

  1. Redis事務與Mysql事務我們知道關係性資料庫Mysql中具有事務的四大特性:「原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、永續性(Durability)」。

  2. 但是Redis的事務為了保證Redis除了客戶端的請求高效,去除了傳統關係型資料庫的「事務回滾、加鎖、解鎖」這些消耗效能的操作,Redis的事務實現簡單。

  3. 原子性中Redis的事務只能保證單個命令的原子性,多個命令就無法保證,如上面索道的執行時錯誤,即使中間有執行時錯誤出現也會正確的執行後面正確的命令,不具有回滾操作。

  4. 既然沒有了原子性,資料的一致性也就無法保證,這些都需要程式設計師自己手動去實現。Reids在進行事務的時候,不會被中斷知道事務的執行結束,也具有一定的隔離性,並且Redis也能持久化資料。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章