Redis事務原理分析


Redis事務原理分析

基本應用

在Redis的事務里面,采用的是樂觀鎖,主要是為了提高性能,減少客戶端的等待。由幾個命令構成:WATCH, UNWATCH, MULTI, EXEC, DISCARD。
通過WATCH,可以實現CAS操作。使用WATCH監聽一些鍵,然后去檢查鍵的值,然后根據鍵的值來決定是否還需要進行MULTI,如果鍵的值被改了,則重新。(因為有可能在執行WATCH前,鍵的值被改了,所以需要先WATCH,然后再作判斷)。在執行MULTI命令后,如果中途WATCH的鍵的值被修改了,后續再執行EXEC時,整個事務都會被終止。

CAS使用示例:
假設存在一個String類型的狀態值,state,需要對其進行CAS操作:

   WATCH state
   value  = GET state;
   if value == 1
	   UNWATCH state
	   Return false;
   MULTI
   SET state 1
   result = EXEC
   if result == success
       return true;
   return false;

原理

Redis事務實現原理

通過上述的基本應用可以知道,Redis是通過WATCH命令,來保證當前事務的數據是否被修改過,如果被修改了,則整個事務會中止,不再執行。那么,Redis在實現的時候,會保存對應的watch key,然后中途如果該Key被修改了,則會將對應的所有客戶端的標志位都置為CLIENT_DIRTY_CAS,表示數據被修改,后續執行EXEC的時候則會被中斷,從而實現事務。而UNWATCH命令則是從保存的watch_keys里面移除。MULTI命令僅僅將客戶端的標志位flags置為CLIENT_MULTI,表示處於MULTI狀態,該狀態下,后續的命令(除了MULTI/WATCH/DISCARD/EXEC)外,其它命令都會被保存到一個列表里面,直到EXEC或者DISCARD命令執行。如果中途出現了語法錯誤之類的命令,則會將flags置為CLIENT_DIRTY_EXEC。后續執行EXEC時,如果flags存在CLIENT_DIRTY_CAS或者CLIENT_DIRTY_EXEC,則整個事務會被中止,不執行任何命令。

ACID分析

針對Redis的事務實現,對於ACID,個人認為,對於Atomicity和Durability以及Consistency,Redis是不滿足的。為什么會對ACID進行分析呢,一部分原因是為了作對比學習,另一部分是因為《Redis設計與實現》19章事務ACID性質里面提到了一些觀點,個人不太認同,所以進行了一些對比。

  1. Atomicity
    指的是要么不執行,要么全部執行。當其中一部分執行了,但是另外一部分沒有執行,那么作為整個事務,是全部要回滾,都不執行的,而Redis在執行過程中,如果出現操作和類型不一致,則會導致一部分執行,而一部分錯誤的情況,即不滿足原子性。當然,除去部分失誤外,還是能夠保證原子性的,但是這並不是嚴格的原子性要求。
  2. Durability
    持久性,事務提交后,無論出現任何情況,包括系統斷電之類的,重啟后都是可以恢復的。對於Redis來說,即使開啟了AOF以及設置為always,也存在命令執行一部分后,系統宕機而導致數據不一致的情況,不能恢復。一般都是通過write-ahead-logging來實現的,即事先寫日志,而Redis是邊執行邊寫日志。
  3. Consistency
    一致性,指從一個有效的狀態轉到另一個有效的狀態,不滿足上述的兩個條件,也無法保存一致性,即會出現中間狀態。比如從一個人的賬戶轉到另外一個人上面,執行了轉出,但是沒有執行轉入的時候宕機了,就會導致數據的不一致。
  4. Isolation
    隔離性,在多個事務並發的情況下,事務之間不會被影響。對於Redis來說,事務的執行是串行的,中途不會插入其它命令的執行,所以是滿足隔離性的。

WATCH命令實現

WATCH監聽Key,首先就要有地方保存監聽的Key,Redis針對不同的客戶端,會在客戶端的結構體里面維護一個WATCH監聽Key的列表,以及在Server里面維護一個全局的哈希表,Key為被監聽的Key,Value則為一個鏈表,里面保存了所有監聽該Key的客戶端。如下圖:

當執行WATCH account時,則首先會判斷該Key是否已在客戶端里面,如果存在,則直接返回,否則加入到客戶端對應的watched_keys列表里面,然后再將其加入到對應DB的watched_keys字典表里面,Key為 account,Value則為該客戶端。

參考資料:

  1. Redis文檔:https://redis.io/topics/transactions
  2. 《Redis實戰》 ch4.4/ch19
  3. Wiki ACID:https://en.wikipedia.org/wiki/ACID
  4. Wiki write-ahead-logging:https://en.wikipedia.org/wiki/Write-ahead_logging
  5. Wiki shadow paging: https://en.wikipedia.org/wiki/Shadow_paging


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM