作者 | Video++極鏈科后端Team劉聰
整理 | 包包
所謂事務(Transaction) ,是指作為單個邏輯工作單元執行的一系列操作。事務必須滿足ACID原則(原子性、一致性、隔離性和持久性)。簡單來說事務其實就是打包一組操作(或者命令)作為一個整體,在事務處理時將順序執行這些操作,并返回結果,如果其中任何一個環節出錯,所有的操作將被回滾。
在Redis中實現事務主要依靠以下幾個命令來實現:
Redis事務從開始到結束通常會通過三個階段:
1.事務開始
2.命令入隊
3.事務執行
以下是一個最簡單的Redis事務流程:
第一步跟其他的關系型數據庫類似,也是需要開啟一個事務,在Redis中的命令如下:
Redis中使用MULTI命令標記事務的開始,可以理解為在傳統關系型數據庫中的BEGIN TRANCATION語句,Redis將執行該命令的客戶端從非事務狀態切換成事務狀態,這一切換是通過在客戶端狀態的flags屬性中打開REDIS_MULTI標識完成, 我們看下Redis中對應部分的源碼實現:
在打開事務標識的客戶端里,這些命令都會被暫存到一個命令隊列里,不會因為用戶會的輸入而立即執行。
第二步就是執行事務內路基,即真正的業務邏輯:
最后一個階段是提交事務(或者回滾事務):
這兩個命令可被視為等同于關系型數據庫中的COMMIT/ROLLBACK語句。
這里需要注意的是,在客戶端打開了事務標識后,只有命令:EXEC,DISCARD,WATCH,MULTI命令會被立即執行,其它命令服務器不會立即執行,而是將這些命令放入到一個事務隊列里面,然后向客戶端返回一個QUEUED回復 ;Redis客戶端有自己的事務狀態,這個狀態保存在客戶端狀態mstate屬性中,mstate的結構體類型是multiState,我們看下multiState的定義:
我們再看下結構體類型multiCmd的結構:
事務隊列以先進先出的保存方法,較先入隊的命令會被放到數組的前面,而較后入隊的命令則會被放到數組的后面。
當開啟事務標識的客戶端發送EXEC命令的時候,服務器就會執行,客戶端對應的事務隊列里的命令,我們來看下EXEC 的實現細節:
最后我們再回顧一下事務本身的特性, 在傳統關系型數據庫中的事務必須依靠ACID來保證事務的可靠性和安全性,在Redis中事務總是具有一致性(Consistency)和隔離性(Isolation),并且當Redis運行在某種特定的持久化模式下,事務也具有耐久性(Durability); 但是并不總是能夠保證原子性(Atomicity),在正常狀態下一個事務的所有命令是能按照原子性的原則執行的,但是執行的中途遇到錯誤,不會回滾,而是繼續執行后續命令, 如下:
如果在set k2 v2處失敗,set k1已成功不會回滾,set k3還會繼續執行;Redis的事務和傳統的關系型數據庫事務的最大區別在于,Redis不支持事務的回滾機制,即使事務隊列中的某個命令在執行期間出現錯誤,整個事務也會繼續執行下去,直到將事務隊列中的所有命令都執行完畢為止,我們看下面的例子:
Redis的作者在事務功能的文檔中解釋說,不支持事務回滾是因為這種復雜的功能和Redis追求的簡單高效的設計主旨不符合,并且他認為,Redis事務的執行時,錯誤通常都是編程錯誤造成的,這種錯誤通常只會出現在開發環境中,而很少會在實際的生產環境中出現,所以他認為沒有必要為Redis開發事務回滾功能。所以我們在討論Redis事務回滾的時候,一定要區分命令發生錯誤的時候。
發布評論請先 登錄
相關推薦
評論