詳細介紹了Redis的事務機制。
MULTI、EXEC、DISCARD 和 WATCH 指令是 Redis 中事務的基礎,它們允許将多個指令組合在一起以事物的方式執行。
DISCARD指令用于清除所有先前在一個事務中放入隊列的指令,然後恢複正常的連接配接狀态。而當某個事務需要按條件執行時,就要使用WATCH指令将給定的鍵設定為受監控的。
一個最簡單的事務從開始到執行大概會經曆以下三個階段:
- MULTI指令開始事務。
- 多個指令入隊。
- EXEC執行事務。
如下案例:
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> SADD a bb cc
QUEUED
127.0.0.1:6379(TX)> SREM a cc
QUEUED
127.0.0.1:6379(TX)> EXEC
1) (integer) 1
2) (integer) 1
Redis有如下保證:
- 事務中的所有指令都被序列化并按順序執行。事務在執行的過程中,不會被其他用戶端發送來的指令請求所打斷。這保證了這一組指令作為單個隔離操作執行。
- 要麼執行所有指令,要麼不執行任何指令。
EXEC
指令會觸發事務中所有指令的執行,如果用戶端在調用EXEC指令之前出現錯誤,比如指令文法錯誤(參數的數量錯誤、指令名稱錯誤等等),比如達到了某些系統限制(比如記憶體溢出)等,此時Redis在執行放入隊列操作的時候會傳回一個錯誤,用戶端将會終止事務,并且丢棄這個事務。
如果成功調用了 EXEC 指令,則會執行所有指令,但是在執行途中可能會遇到某個指令失敗,比如對key執行了錯誤的操作(比如對String類型的資料執行的list的指令),此時Redis不會對此前的指令進行任何復原,也不會影響後續指令的執行,是以不具備嚴格的原子性。
使用AOF持久化機制時,Redis 確定使用一個write()函數系統調用将事務的所有操作同時寫入磁盤(寫入核心緩沖區)。但如果Redis 伺服器崩潰或被直接kill掉,則可能隻持久化了部分操作。是以,事物的持久性也不能保證。Redis 将在重新啟動時檢測到這種情況,并會出現錯誤退出。使用 redis-check-aof 工具可以修複将删除部分事務的aof檔案,以便伺服器可以重新啟動。
總的來說,Redis事務和資料庫事務有很多差別,Redis事務可以了解為一個打包的批量執行腳本,但批量指令并非原子化的操作,中間某條指令的失敗不會導緻前面已執行指令的復原,也不會造成後續的指令不執行。
為什麼Redis的事務不支援復原呢? 從官網能找到答案:
- Redis開發者覺得沒必要支援復原,這樣Redis内部能夠保持更簡單便捷并且性能更好。
- Redis開發者覺得失敗的指令是由使用者程式設計錯誤造成的,而這些錯誤應該在開發的過程中被發現,而不應該出現在生産環境中。
Redis事務實際上用的并不是很多,另外,Redis的LUA腳本也是事務型的。是以,我們可以通過Redis事務實作的功能,同樣也可以通過Redis腳本來實作,而且通常腳本更簡單、更快速。Redis開發者說過:如果整個使用者群體都隻使用Redis腳本,那麼将會廢棄,甚至最終移除Redis事務。
相關文章:
- https://redis.io/topics/data-types
- https://redis.io/topics/data-types-intro
- https://redis.io/topics/transactions
如有需要交流,或者文章有誤,請直接留言。另外希望點贊、收藏、關注,我将不間斷更新各種Java學習部落格!