事務的定義
事務是一組具備原子性操作的命令集合。在這一組命令中,要么全部執行成功,要么全部執行失敗。
事務的特點
- 原子性。原子性指的是事務操作具備原子操作,一個事務里面的 SQL 操作要么全部成功要么全部失敗,不能存在一些 SQL 成功,一些 SQL 執行失敗。
- 隔離性。隔離性指的是多個事務之間是相互隔離的,事務之間是互不受影響的。
- 持久性。持久性指的是事務一旦提交,就不能進行回滾(撤回),永久的保存在磁盤中。
- 一致性。一致性指的是事務操作前后必須滿足業務約束。
有關事務的四大特性的具體講解可以參考該文章
http://mindoc.qqdeveloper.com/docs/mysql/mysql-1cj2eksj770bg
Redis事務執行邏輯
Redis在事務中的命令是添加到一個命令隊列里面,等待事務提交之后,則一一執行命令隊列里面的命令。
Redis事務命令
- multi:開啟事務。
- exec:提交當前事務。
- discard:取消當前事務。
- watch:監聽key是否在事務開啟之前被其他命令修改,如果被修改去不處理事務內的操作。
- unwatch:取消監聽key是否在事務開啟之前被其他的命令修改。
命令演示
- 事務執行流程。
客戶端一:負責開啟事務并寫入緩存數據。
127.0.0.1:6379> multiOK127.0.0.1:6379> set user:id:1 1QUEUED127.0.0.1:6379> exec1) 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"
- watch對key監聽。
客戶端一:負責開啟事務,并使用watch監聽key。
# 監聽key之前查看值127.0.0.1:6379> get age"1"# 開啟監聽127.0.0.1:6379> watch ageOK# 開啟事務127.0.0.1:6379> multiOK# 修改被監聽的key值127.0.0.1:6379> set age 2QUEUED# 提交事務(發現返回的是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 3OK# 在客戶端一執行exec命令之后執行。127.0.0.1:6379> get age"3"
通過2中的演示,你會發現在事務開啟之前對key做了監聽。事務正常提交之后,被監聽的key在事務中執行的命令是不會被執行的。unwatch對監聽的key,取消監聽事件。此時的取消監聽不能放在事務中,只能在事務開啟之前對key的監聽事件做取消。 事務命令異常處理
事務原子性演示
- 命令錯誤的原子性。
127.0.0.1:6379> multiOK127.0.0.1:6379> set user:name zhangsanQUEUED127.0.0.1:6379> set user:age 1QUEUED127.0.0.1:6379> set user:sex maxQUEUED# 執行一條命令錯誤的操作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"
通過上面的演示,在事務中執行一條錯誤的語法命令,整個事務都將不會被執行。
- 內部語法使用錯誤。
127.0.0.1:6379> get name"zhangsan"127.0.0.1:6379> multiOK127.0.0.1:6379> set mu:id 1QUEUED# 執行一個語法不當的操作127.0.0.1:6379> incr nameQUEUED127.0.0.1:6379> set mu:age 2QUEUED127.0.0.1:6379> exec1) OK2) (error) ERR value is not an integer or out of range3) OK
通過上面的演示,在事務中執行了一條語法不當的的操作,最終提交事務后。事務中的正確命令依舊不被執行了。這不符合事務原子性的特點。
事務原子性總結。
a. 當事務中存在語法使用不當的情況時,事務會跳過當前的命令。其他的正確命令依舊被執行。
b. Redis中的事務并非一定滿足原子性的特點。
c. 在事務中,執行的命令,Redis只會檢測是否是一個合法的命令。如果合法則添加到命令隊列,如果不合法則直接阻止整個事務的執行。
常見問題總結
MySQL中的事務與Redis事務的區別
Redis事務與Mysql事務我們知道關系性數據庫Mysql中具有事務的四大特性:「原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)」。
但是Redis的事務為了保證Redis除了客戶端的請求高效,去除了傳統關系型數據庫的「事務回滾、加鎖、解鎖」這些消耗性能的操作,Redis的事務實現簡單。
原子性中Redis的事務只能保證單個命令的原子性,多個命令就無法保證,如上面索道的運行時錯誤,即使中間有運行時錯誤出現也會正確的執行后面正確的命令,不具有回滾操作。
- 既然沒有了原子性,數據的一致性也就無法保證,這些都需要程序員自己手動去實現。Reids在進行事務的時候,不會被中斷知道事務的運行結束,也具有一定的隔離性,并且Redis也能持久化數據。