讀取修復
讀取修復是在讀取要求期間修復資料複本的程序。如果在給定讀取一致性層級中參與讀取要求的所有複本都一致,則資料會傳回給客戶端,且不需要讀取修復。但是,如果在給定一致性層級中參與讀取要求的複本不一致,則會執行讀取修復,以使參與讀取要求的複本一致。最新的資料會傳回給客戶端。讀取修復在前景執行,且會封鎖,因為在讀取修復完成且建構最新資料之前,不會傳送回應給客戶端。
預期單調一致性讀取
Cassandra 使用封鎖讀取修復來確保「單調一致性讀取」的預期,即在 2 次連續的一致性讀取中,保證第 2 次讀取不會比第 1 次讀取更舊,即使失敗的一致性寫入僅對少數複本執行最新值寫入。
單調讀取的表格層級設定
Cassandra 4.0 新增對單調讀取的表格層級設定支援 (CASSANDRA-14635)。read_repair
表格選項已新增至表格架構,選項為 blocking
(預設) 和 none
。
read_repair
選項設定讀取修復行為,以調整各種效能和一致性行為。讀取修復行為會影響兩個一致性屬性。
-
單調一致性讀取:由
BLOCKING
提供。單調一致性讀取可防止讀取在某些情況下看似回到過去。當不提供單調一致性讀取,且寫入未達到複本的一致性時,它可能會在一次讀取中可見,然後在後續讀取中消失。 -
寫入原子性:由
NONE
提供。寫入原子性可防止讀取傳回部分套用的寫入。Cassandra 嘗試提供區段層級寫入原子性,但由於讀取修復僅修復SELECT
陳述式涵蓋的資料,因此當資料以比寫入更細緻的層級讀取時,讀取修復可能會中斷寫入原子性。例如,如果您將多列寫入群集區段中的批次,但隨後在SELECT
陳述式中指定群集欄位來選取單一列,則讀取修復可能會中斷寫入原子性。
可用的讀取修復設定為
讀取修復範例
為了說明讀取修復,請考慮客戶端傳送讀取要求,讀取一致性層級為 TWO
至 5 節點叢集,如圖 1 所示。讀取一致性層級決定讀取要求在被視為成功之前,必須有多少個複本節點傳回回應。

圖 1. 客戶端傳送讀取要求至 5 節點叢集
三個節點主機要求的資料複本,如圖 2 所示。讀取一致性層級為 TWO
,兩個複本節點必須傳回回應,讀取要求才被視為成功。如果客戶端傳送要求的節點主機要求的資料複本,則僅需傳送讀取要求至另一個複本節點。但如果接收節點未主機要求的資料複本,則節點會變成協調器節點,並將讀取要求轉送至主機複本的節點。直接讀取要求會轉送至最快的節點(由動態 snitch 決定),如圖 2 所示。直接讀取要求是完整讀取,並傳回要求的資料。

圖 2. 直接讀取要求傳送至最快的複本節點
接著,協調器節點會傳送必要的其他要求,以滿足一致性層級,也就是 TWO
。協調器節點需要再傳送一個讀取要求,總共兩個。除了第一個直接讀取要求之外,所有讀取要求都是摘要讀取要求。摘要讀取要求不是完整讀取,只會傳回資料的雜湊值。只會傳回雜湊值,以減少網路資料流量。在所討論的範例中,協調器節點會傳送一個摘要讀取要求至主機複本的節點,如圖 3 所示。

圖 3. 協調器傳送摘要讀取要求
協調器節點已從一個節點接收資料的完整副本,並從另一個節點接收資料的雜湊值。為了比較傳回的資料,會針對資料的完整副本計算雜湊值。比較兩個雜湊值。如果雜湊值相同,則不需要讀取修復,且會將所要求資料的完整副本傳回給客戶端。協調器節點只執行總共兩個複本讀取要求,因為範例中的讀取一致性層級為 TWO
。如果一致性層級較高,例如 THREE
,則三個複本節點需要回應讀取要求,且只有當所有摘要或雜湊值都與資料完整副本的雜湊值相符時,讀取要求才會被視為成功,且資料會傳回給客戶端。
但是,如果摘要讀取要求的雜湊值與第一個複本節點的完整讀取要求的資料雜湊值不同,則表示複本中存在不一致性。為了修正不一致性,會執行讀取修復。
例如,假設摘要要求傳回的雜湊值與直接完整讀取要求的資料雜湊值不同。我們需要讓複本保持一致,因此協調器節點會傳送直接 (完整) 讀取要求給先前已傳送摘要讀取要求的複本節點,如圖 4 所示。

圖 4. 協調器傳送直接讀取要求給已傳送摘要讀取要求的複本節點
在從第二個副本節點收到資料後,協調器會從兩個副本節點取得資料。由於範例中的讀取一致性層級為 TWO
,因此它只需要兩個副本。會比較兩個副本的資料,並根據時間戳記選取最新的副本。如果一個副本僅包含部分欄位的資料,則可能需要合併資料才能建構最新的資料副本。在範例中,如果發現第一個直接讀取要求的資料已過時,而第二個完整讀取要求的資料為最新讀取,則需要對副本 2 執行修復。如果透過合併兩個副本建構新的最新資料,則需要對所涉及的兩個副本執行讀取修復。例如,如圖 5 所示,對副本 2 執行讀取修復。

圖 5. 協調器執行讀取修復
最新資料會傳回給客戶端,如圖 6 所示。在三個副本中,副本 1 甚至未讀取,因此未修復。副本 2 已修復。副本 3 為最新資料,並傳回給客戶端。

圖 6. 最新資料傳回給客戶端
讀取一致性層級與讀取修復
讀取一致性在決定是否需要執行讀取修復時是最重要的因素。如表 1 所述,並非所有一致性層級都需要讀取修復。
表 1. 根據讀取一致性層級進行讀取修復
讀取一致性層級 | 說明 |
---|---|
ONE |
不執行讀取修復,因為第一個直接讀取要求的資料符合一致性層級 ONE。不涉及摘要讀取要求來尋找資料中的不符。 |
TWO |
如果根據直接和摘要讀取要求發現資料不一致,則執行讀取修復。 |
THREE |
如果根據直接和摘要讀取要求發現資料不一致,則執行讀取修復。 |
LOCAL_ONE |
不執行讀取修復,因為從最接近副本的直接讀取要求的資料符合一致性層級 LOCAL_ONE。不涉及摘要讀取要求來尋找資料中的不符。 |
LOCAL_QUORUM |
如果根據直接和摘要讀取要求發現資料不一致,則執行讀取修復。 |
QUORUM |
如果根據直接和摘要讀取要求發現資料不一致,則執行讀取修復。 |
如果執行讀取修復,則僅在未更新且參與讀取請求的複本上執行。參與讀取請求的複本數量將基於讀取一致性層級;在範例中為兩個。
Cassandra 4.0 中改善的讀取修復封鎖行為
Cassandra 4.0 對讀取修復封鎖行為進行兩項改善 (CASSANDRA-10726)。
-
完整資料讀取請求的推測重試。如果未收到完整資料回應,無論是在初始完整讀取請求中或是在讀取修復期間的完整資料讀取請求中,Cassandra 4.0 會在將讀取請求 (完整,非摘要) 傳送至複本時使用推測重試。使用推測重試時,如果看起來可能無法從 Cassandra 傳送訊息的初始複本組收到回應以滿足一致性層級,則它會推測性地將額外的讀取請求傳送至未聯繫的複本。如果看起來其中一個可能不會回應,Cassandra 4.0 也會推測性地將修復突變傳送至未參與讀取修復資料讀取/寫入週期的少數節點,其中包含所有未確認突變的合併內容。只要 Cassandra 收到的確認數量與傳輸的修復突變數量相同,它就會接受來自它們的確認,而不是來自傳送的初始突變的確認。
-
僅封鎖對完整資料回應以滿足一致性層級。Cassandra 4.0 僅封鎖解析摘要不匹配所需的內容,並等待足夠的完整資料回應以符合一致性層級,無論是推測重試或讀取修復機會。例如,如果看起來 Cassandra 可能無法及時從所有人那裡收到完整資料請求,它會將額外的請求傳送至初始完整資料讀取中未聯繫的額外複本。如果最終及時回應的節點集合最終同意資料,則不會考慮啟動讀取修復的不一致複本的回應,也不會包含在對客戶端的回應中,從而保留單調法定人數讀取的預期。
讀取修復的診斷事件
Cassandra 4.0 新增讀取修復的診斷事件 (CASSANDRA-14668),可用於揭露以下資訊
-
已聯繫的端點
-
端點的摘要回應
-
受影響的分區金鑰
-
推測的讀取/寫入
-
更新過大
背景讀取修復
背景讀取修復已從 Cassandra 4.0 中移除 (CASSANDRA-13910),該修復使用 cassandra.yaml 中的 read_repair_chance 和 dclocal_read_repair_chance 設定進行設定。
讀取修復並非其他類型修復的替代方案,例如完整修復或更換持續發生故障的節點。即使在執行讀取修復後傳回的資料,若一致性層級並非需要所有複製品回應的層級,則可能不是最新的資料。