Redis 事務

Redis 提供的事務機制與傳統的數據庫事務有些不同,傳統數據庫事務必須維護以下特性:原子性(Atomicity),  一致性(Consistency),  隔離性(Isolation),  持久性(Durability),簡稱ACID。
我們逐項考察下 Redis 在事務的 ACID 上做出的權衡與取捨:

原子性(Atomicity)
原子意味着操作的不可再分,要麼執行要麼不執行。Redis 本身提供的所有 API 都是原子操作,那麼 Redis 事務其實是要保證批量操作的原子性。Redis 實現批量操作的原理是在一個事務上下文中(通過 MULTI命令開啓),所有提交的操作請求都先被放入隊列中緩存,在 EXEC 命令提交時一次性批量執行。這樣保證了批量操作的一次性執行過程,但 Redis 在事務執行過程的錯誤情況做出了權衡取捨,那就是放棄了回滾。
Redis 官方文檔對此給出的解釋是:
  1. Redis 操作失敗的原因只可能是語法錯誤或者錯誤的數據庫類型操作,這些都是在開發層面能發現的問題不會進入到生產環境,因此不需要回滾。
  2. Redis 內部設計推崇簡單和高性能,因此不需要回滾能力。
據實而說第一條說法感覺有點站不住腳,可以想象得到 Redis 操作失敗的原因絕對不止語法層面的錯誤,特別是一些像依賴操作系統、文件系統的操作。第二條說法更實在,Redis 的應用場景明顯不是爲了數據存儲的高可靠而設計的,而是爲了數據訪問的高性能而設計,設計者爲了簡單性和高性能而部分放棄了原子性。
出於以上考慮 Redis 的事務執行有以下特點:
  1. 批量操作在發送 EXEC 命令前被放入隊列緩存
  2. 收到 EXEC 命令後進入事務執行,事務中任意命令執行失敗,其餘的命令依然被執行
  3. 在事務執行過程,其他客戶端提交的命令請求不會插入到事務執行命令序列中
一致性(Consistency)
一致性意味着事務結束後系統的數據依然保證一致。在事務開始之前,數據保持有效的狀態,事務結束後也如此。顯然在前面討論原子性時,Redis 捨棄了回滾的設計,基本上也就捨棄對數據一致性的有效保證。不過對於一個高效的 key-value store 或 data structure server,數據操作一致性很多時候更多應該依賴應用層面,事實也是我們使用 Redis 時很多時候都是分片和集羣的,數據一致性無法依靠任何事務機制。

隔離性(Isolation)
隔離性保證了在事務完成之前,該事務外部不能看到事務裏的數據改變。也不能訪問一些中間狀態,因爲假如事務終止的話,這些狀態將永遠不會發生。Redis 採用單線程設計,在一個事務完成之前,其他客戶端提交的各種操作都無法執行因此自然沒法看見事務執行的中間狀態,隔離性得到保證。

持久性(Durability)
Redis 一般情況下都只進行內存計算和操作,持久性無法保證。但 Redis 也提供了2種數據持久化模式,SNAPSHOT 和 AOF,SNAPSHOT的持久化操作與命令操作是不同步的,無法保證事務的持久性。而AOF模式意味着每條命令的執行都需要進行系統調用操作磁盤寫入文件,可以保證持久性,但會大大降低 Redis 的訪問性能。

Redis 在2.6版本開始提供腳本(Lua scripting)能力,一種更靈活的批量命令組織方式用於取代目前的事務機制。腳本提供了更強大和靈活的編程能力,但也是一把雙刃劍,由於 Redis 需要保證腳本執行的原子性和隔離性,腳本執行期間會阻塞其他命令的執行,因此建議寫一些高效的腳本。不過從開發者的角度來說使用Lua腳本的成本(學習成本、開發成本、維護成本)都要更大,特別是一些開發者如果將應用的業務邏輯放入腳本中來執行,是不是讓人想起了數據庫的存儲過程。
發佈了132 篇原創文章 · 獲贊 38 · 訪問量 42萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章