技術基礎 | 捨棄”讀修復概率”特性

DataStax發表於2021-02-07
讀修復這個特性給系統施加了額外的負載,卻沒有任何實質好處——這就是為什麼我們一直以來都會建議大家先關閉這個特性;這也是在下一個Cassandra主要的版本,即Cassandra 4.0版本中,將這個特性完全拿掉的根本原因。

 
Apache Cassandra有一個叫做讀修復概率(Read Repair Chance)的特性,通常我們都會建議我們的使用者關閉這個功能,因為它經常會給你的叢集內部增加大約20%的讀負載成本,但這樣的成本付出卻目的不明且效果難保。

 
01 什麼是讀修復概率?
 
Read Repair Chance可以通過兩個資料表級別的模式(schema)選項來進行設定:read_repair_chancedclocal_read_repair_chance。這兩個選項都代表著在要求的一致性級別(consistency level)之上,協調節點(coordinator node)為了進行讀修復而向額外的副本節點(replica node)傳送請求的概率。
 
read_repair_chance原始設定決定了在所有資料中心範圍內,向所有副本傳送額外請求的概率。而後來出現的dclocal_read_repair_chance設定則決定了在本地的資料中心範圍內,向所有副本傳送額外請求的概率。
 
預設值是read_repair_chance = 0.0以及dclocal_read_repair_chance = 0.1。這意味著跨資料中心的非同步讀修復預設是被關閉的,而在本地資料中心範圍內的非同步讀修復發生的概率是收到的讀取請求數量的10%。

 
02 讀修復的成本幾何?
 
考慮一下下面的叢集部署方案:
  • 在一個單獨的資料中心裡有一個鍵空間,其複製因子(replication factor)為3,即RF=3
  • 預設值是dclocal_read_repair_chance = 0.1
  • 客戶端讀取的一致性級別為LOCAL_QUORUM
  • 客戶端使用大多數驅動程式預設的token aware policy
 
在這種設定之下,叢集將有大約10%的讀取請求會導致協調節點需要不僅向一個副本節點,而是要向兩個副本節點傳送訊息系統請求。而這會導致大約5%的額外負載。
 
如果要求的一致性級別是Java驅動程式預設的LOCAL_ONE,那麼大約有10%的讀取請求會導致協調節點將訊息系統請求的數量從0增加到2。而這意味著大約20%的讀負載的增加。
 
read_repair_chance = 0.1且多資料中心的條件下,情況就更糟糕了。如果有3個RF=3的資料中心,那麼10%的讀請求會導致協調節點向8個額外的副本節點傳送請求,且去往其中的6個副本節點的請求將需要跨資料中心。這種情況下,讀負載將會翻倍。
 
讓我們通過幾張火焰圖(flamegraph)來看看這個問題吧。
 
第一張火焰圖展示的是dclocal_read_repair_chance = 0.1的預設配置下的情況。當協調節點的程式碼走到AbstractReadExecutor.getReadExecutor(..)方法時,下一步就會根據表格的ReadRepairDecision引數的值來執行不同路徑的程式碼了。
 
有關AlwaysSpeculatingReadExecutorSpeculatingReadExecutorNeverSpeculatingReadExecutor的棧追蹤(stack trace)資訊可以幫我們瞭解系統正在執行哪條路徑上的程式碼,以及到底是read repair chance還是推測性重試(speculative retry)正在被執行。
 
技術基礎 | 捨棄”讀修復概率”特性
 
第二張火焰圖展示的是當配置被改成dclocal_read_repair_chance = 0.0之後的情況。可以看到AlwaysSpeculatingReadExecutor的那支火焰降下去了,這顯示出系統執行時的複雜程度降低了。
 
具體來說,複雜度的降低是因為從客戶端發來的讀請求在這種情況下會被轉發給每一個副本節點,而非僅僅轉發給一致性級別定義的那些副本。
 
技術基礎 | 捨棄”讀修復概率”特性
 
這兩張火焰圖均是在使用Apache Cassandra 3.11.9、Kubernetes和cass-operator、nosqlbench以及async-profiler的情況下生成的。
 
以前,我們需要依賴於已有的tlp-cluster、ccm、tlp-stress和cassandra-stress工具進行測試。而新工具帶來的新測試方式格外地簡單。通過使用k8s,同樣的測試方式可以在本地或針對k8s的基礎架構下使用。也就是說,我們無需在用於本地測試的ccm叢集和用於雲端測試的tlp-cluster中間來回切換。這條適用於所有的地方。我也並不是非要使用AWS做雲端測試。
 
另外還值得一提的是這些新工具得到了來自DataStax的很多關注和支援,所以向開源社群介紹這些是值得的。

 
03 用額外的負載換得的好處是什麼?
 
根據使用者要求的一致性級別,當協調節點從多個副本節點中的任意一個獲得回覆後,它就會將這個結果返回給客戶端。這也是為什麼我們將這個特性稱為“非同步”讀修復——雖然額外的後臺負載會間接地影響讀取操作的時延,但是這種影響並不是直接的。
 
非同步的讀修復同時意味著返回給客戶端的結果不一定是修復後的資料。總的來說,你讀取的資料中的10%是一定會在你讀取之後被修復的。
 
而這個修復概率並不是對客戶端來說被保證的概率,各種Cassandra operator也沒法根據它賴以保證磁碟儲存的資料的一致性的。事實上,這種修復概率對Cassandra operator沒有什麼保證,因為大多數不一致的資料都由hints處理,而節點當機時間長於hint視窗的情況則需要手動修復。
 
除此之外,使用強一致性的系統(如讀寫操作都使用QUORUM作為一致性級別的系統)並不會出現這種資料未修復的情況。
 
這種系統需要做repair操作和磁碟上的資料一致性只是為了降低讀取操作的時延(通過避免協調節點和副本節點之間因digest不匹配而引起的反覆通訊),同時確保已經被刪除的資料不會被錯誤地讀到(即墓碑都被合理且及時地傳送到各個副本)。
 
所以說,讀修復這個特性給系統施加了額外的負載,卻沒有任何實質好處。這就是為什麼我們一直以來都會建議大家先關閉這個特性。也是在下一個Cassandra主要的版本,即Cassandra 4.0版本中,將這個特性完全拿掉的根本原因。
 
從3.0.17 和3.11.3版本開始,如果你仍在你的資料庫表中設定了與這些屬性相關的值,你可能會在系統啟動時看到如下警告:
dclocal_read_repair_chance table option has been deprecated and will be removed in version 4.0

 
04 現在就捨棄讀修復吧
 
如果你使用的是4.0版本以前的Cassandra叢集,下方程式碼可關閉非同步讀修復功能:
cqlsh -e 'ALTER TABLE <keyspace_name>.<table_name> WITH read_repair_chance = 0.0 AND dclocal_read_repair_chance = 0.0;'

 

如果你已經升級到了Cassandra 4.0,那麼你無需任何額外操作,因為讀修復相關的設定已經被忽略和刪除了。

相關文章