Cassandra 文件

版本

您正在檢視預發行版本的說明文件。

檢視最新版本

改進的節點間訊息傳遞

Apache Cassandra 4.0 已新增多項節點間訊息傳遞的新進階功能。

最佳化的節點間訊息傳遞協定

節點間訊息傳遞協定已最佳化 (CASSANDRA-14485)。先前,傳送者的 IPAddressAndPort 會包含在每則傳送的訊息中,即使在建立初始連線/工作階段時已傳送過 IPAddressAndPort。在 Cassandra 4.0 中,已從每則傳送的個別訊息中移除 IPAddressAndPort,並僅在啟動連線/工作階段時傳送。

另一項進階功能是,在多個執行個體 (已列出) 中,已將固定的 4 位元組整數值替換為 vint,因為 vint 幾乎都小於 1 位元組

  • paramSize (標頭中的參數數目)

  • 每個個別參數值

  • payloadSize

NIO 訊息傳遞

在 Cassandra 4.0 中,對等 (節點間) 訊息傳遞已透過 Netty 切換為非同步 I/O (NIO) (CASSANDRA-8457)。

作為序列化格式,每則訊息都包含一個標頭,其中有數個固定欄位、一個選用的鍵值參數區段,然後是訊息酬載本身。注意:標頭中的 IP 位址可能是 IPv4 (4 位元組) 或 IPv6 (16 位元組)。

下圖簡要顯示 IPv4 位址。

1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 4 4 4 4 4 5 5 5 5 5 6 6
0 2 4 6 8 0 2 4 6 8 0 2 4 6 8 0 2 4 6 8 0 2 4 6 8 0 2 4 6 8 0 2
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       PROTOCOL MAGIC                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                         Message ID                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                         Timestamp                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Addr len |           IP Address (IPv4)                       /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/           |                 Verb                              /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/           |            Parameters size                        /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/           |             Parameter data                        /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        Payload size                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               /
/                           Payload                             /
/                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

個別參數具有字串金鑰和位元組陣列值。金鑰會以其長度序列化,編碼為兩個位元組,後接字串的 UTF-8 位元組編碼。主體會以其長度序列化,編碼為四個位元組,後接值位元組。

排隊訊息的資源限制

透過對排隊的傳出訊息數量強制執行嚴格的資源限制 (CASSANDRA-15066),可改善系統穩定性,訊息的數量以 serializedSize 衡量。同時實施三個獨立的限制,以確保在任何合理的故障組合影響節點穩定性的情況下,都能持續進度。

  1. 對排隊傳送至其他節點的訊息,以及等待從叢集中的其他節點到達後處理的訊息,實施整體、每個端點和每個連線的限制。這些限制套用於傳送或接收訊息的線上大小。

  2. 在實施任何端點或整體限制之前,會孤立地消耗基本每個連結限制。每個節點對有三個連結:緊急、小和大型。任何給定的節點最多可以有 N*3 * (internode_application_send_queue_capacity 以位元組為單位 + internode_application_receive_queue_capacity 以位元組為單位) 的訊息資料排隊,而不會在它們之間進行任何協調,儘管在實際上,使用具備代幣感知的路由時,只有 RF*tokens 節點需要以顯著的頻寬進行通訊。

  3. 每個端點限制會同時與整體限制,對叢集中單一節點的所有連結實施在超過每個連結限制的所有訊息上。整體限制會同時與每個端點限制,對叢集中任何節點的所有連結實施在超過每個連結限制的所有訊息上。已將下列設定新增至 cassandra.yaml,以作為排隊訊息的資源限制。

internode_application_send_queue_capacity: 4MiB
internode_application_send_queue_reserve_endpoint_capacity: 128MiB
internode_application_send_queue_reserve_global_capacity: 512MiB
internode_application_receive_queue_capacity: 4MiB
internode_application_receive_queue_reserve_endpoint_capacity: 128MiB
internode_application_receive_queue_reserve_global_capacity: 512MiB

用於傳訊量測的虛擬表格

透過使用虛擬表格來記錄節點間傳入和傳出傳訊量測,可改善量測 (CASSANDRA-15066)。對於傳入傳訊量測,已新增虛擬表格 (internode_inbound) 來記錄

  • 無法序列化或因錯誤而無法沖刷的訊息位元組和數量

  • 已排程訊息的位元組和數量

  • 已成功處理訊息的位元組和數量

  • 已成功接收訊息的位元組和數量

  • 已限制訊息的奈秒和數量

  • 已過期的訊息位元組和數量

  • 已復原和未復原的損毀框架

已新增一個獨立的虛擬表格 (internode_outbound) 用於傳出節點間訊息傳遞。傳出虛擬表格會保留下列指標:

  • 待處理訊息的位元組和數量

  • 已傳送訊息的位元組和數量

  • 已過期的訊息位元組和數量

  • 因錯誤而無法傳送訊息的位元組和數量

  • 已超載訊息的位元組和數量

  • 活動連線數

  • 連線嘗試次數

  • 成功的連線嘗試次數

提示訊息傳遞

已新增一個提示訊息的特殊版本,它會採用已編碼在 ByteBuffer 中的提示,並逐字傳送。這是針對將目前訊息傳遞版本的提示檔案傳送至相同訊息傳遞版本的節點(最常見的情況)而進行的最佳化。它可節省額外的 ByteBuffer 配置和多餘的提示解序列化-序列化循環。

節點間應用程式逾時

已新增一個組態設定至 cassandra.yaml,用於連線在應用程式空間中可能無法寫入的最長連續時間。

# internode_application_timeout_in_ms = 30000

其他一些新功能包括記錄訊息大小至追蹤訊息,以追蹤查詢。

已最佳化本地請求的 Paxos 準備和建議階段

在 4.0 之前的版本中,即使請求要由本地提供服務,Paxos 準備和建議訊息仍會在 Cassandra 中經過整個 MessagingService 堆疊,我們可以加強並讓本地請求在不涉及 MessagingService 的情況下提供服務。Cassandra 中的其他地方也執行類似的工作,會略過本地請求的 MessagingService 階段。

如果我們開啟追蹤並執行輕量級交易,在 4.0 之前的版本中會如下所示

Sending PAXOS_PREPARE message to /A.B.C.D [MessagingService-Outgoing-/A.B.C.D] | 2017-09-11
21:55:18.971000 | A.B.C.D | 15045
… REQUEST_RESPONSE message received from /A.B.C.D [MessagingService-Incoming-/A.B.C.D] |
2017-09-11 21:55:18.976000 | A.B.C.D | 20270
… Processing response from /A.B.C.D [SharedPool-Worker-4] | 2017-09-11 21:55:18.976000 |
A.B.C.D | 20372

建議階段也適用相同的情況。

在 4.0 版本中,已最佳化本地請求的 Paxos 準備和建議階段 (CASSANDRA-13862).

品質保證

4.0 版本中已進行多項其他品質保證改善 (CASSANDRA-15066).

分組

4.0 版本為所有節點間訊息導入分組,也就是將訊息群組成單一邏輯酬載,並附有標頭和尾端;這些框架保證最多只包含一則訊息,該訊息會分割成其自己的獨特框架順序(針對大型訊息),或框架只包含完整訊息。

防範損毀

先前,資料中心內部節點間訊息預設不受損毀保護,因為只有 LZ4 提供任何完整性檢查。傳送至 4.0 節點之後的所有訊息都會寫入明確的框架,這些框架可能是

  • LZ4 編碼

  • CRC 保護

仍提供未受保護的選項。

復原力

為了復原力,所有框架都寫入一個分開的 CRC 保護標頭,分別為 8 和 6 位元組。如果此標頭發生損毀,則必須重設連線,如前所述。如果標頭以外的任何地方發生損毀,則會略過損毀的框架,讓連線保持完整,並避免不必要地遺失任何訊息。

先前,串流中任何一點的任何問題都會導致連線重設,並遺失任何傳輸中的訊息。

效率

傳入和傳出訊息的整體記憶體使用量和位元組交換次數都已減少。

傳出的 Netty LZ4 編碼器會維護一個區塊大小緩衝區 (64KiB),在產生任何壓縮框架之前會先填滿該緩衝區。我們的框架編碼器會避免這種重複複製,並為每個端點釋放 192KiB。

傳入的框架解碼器保證只複製解析框架所需的位元組數,且絕不儲存超過必要的位元組。此改善適用於 LZ4 連線兩次,改善訊息解碼和 LZ4 框架解碼。

傳入路徑

4.0 版本為傳入路徑導入多項改善。

根據旗標中設定的特定連線預期是大訊息還是小訊息,將使用適當的訊息處理常式。在事件迴圈上執行的 NonblockingBufferHandler 用於小訊息,在事件迴圈外執行的 BlockingBufferHandler 用於大訊息。InboundMessageHandler 的單一實作可有效處理任何大小的訊息,方法是從位元組串流中衍生接收訊息的大小。除了從串流中衍生訊息大小外,還主動讀取接收訊息的到期時間,然後才嘗試解除序列化整個訊息。如果在遇到訊息時已過期,則會直接略過位元組串流中的訊息。如果訊息在接收端仍無法解除序列化(例如,因為表格 ID 或欄位未知),則會略過位元組,而不會中斷整個連線並遺失所有緩衝訊息。會立即將失敗原因傳送回協調節點,而不是等到協調節點的回呼過期。此邏輯已延伸至損毀的框架;損毀的框架會安全略過,而不會中斷連線。

接收路徑對記憶體使用量實施嚴格限制。具體來說,所有已剖析但未處理訊息所佔用的記憶體都受到限制,依據每個連線、每個端點和整體為基礎。一旦連線超過其本機未處理容量,且無法從每個端點和整體保留區借用任何許可,便會停止處理更多訊息,提供自然的背壓,直到重新獲得足夠的容量。

傳出連線

開啟連線

針對所有類型的連線失敗採用一致的方法,包括:端點拒絕、版本不相容或意外例外;

  • 持續重試,直到成功或沒有訊息等待傳遞。

  • 在重新連線之前,等待的時間會逐漸增加,最長可達 1 秒。

  • 在連線失敗時,不會取得任何保留佇列限制。

關閉連線

  • 正確排放等待傳遞的傳出訊息(除非已斷線且無法重新連線)。

  • 寫入到正在關閉的連線中的訊息會傳送或拒絕,如果舊的連線無法復原地關閉,則會開啟新的連線。

  • 未使用的連線最終會被剪裁。

重新連線

我們有時需要重新連線一個完全有效的連線,例如在優先 IP 位址變更時。我們會確保基礎連線在關閉和重新連線之前沒有正在進行的作業。

訊息失敗

立即傳播到回呼,透過回收已提交的記憶體來更好地防止過載。

過期
  • 不再經歷佇列開頭的封鎖(例如無法刪除的訊息會阻止所有可刪除的訊息過期)。

  • 在過載時,會在排隊執行緒上積極嘗試過期。

  • 在斷線時,我們會排程定期剪裁,以處理不再傳送訊息,但我們有大量待過期的訊息積壓的情況。

過載
  • 以排隊的位元組追蹤,而不是訊息數量。

序列化錯誤
  • 不會導致連線失效;訊息僅會以失敗完成,然後從框架中刪除。

  • 包括計算的序列化大小與實際大小之間偵測到的不符。

傳輸到網路的失敗,可能是因為連線已重設,目前不會通知回呼處理常式,因為必要的資訊已捨棄,不過如果我們決定值得這麼做,未來可以這麼做。

QoS

「八卦」連線已替換為通用的「緊急」連線,用於任何影響系統穩定的小型訊息。

指標

我們追蹤並透過虛擬表格和 JMX 公開無法因為錯誤而序列化或傳輸的訊息和位元組數量、因為過載或逾時而刪除的訊息、待處理的訊息,以及已成功傳送的訊息。

新增訊息大小限制

Cassandra pre-4.0 無法保護伺服器,以免為節點間訊息物件配置過大的緩衝區。新增訊息大小限制有助於處理問題,例如故障叢集參與者。4.0 版引入了最大訊息大小設定參數,類似於最大變異大小 - 預設設定為保留端點容量。

在反序列化節點間訊息時,從未知資料表中復原

如 (CASSANDRA-9289) 中所述,從其他節點的訊息中看到未知資料表時,能順利復原會很好。在 4.0 版之前,我們會關閉連線並重新連線,這可能會導致其他同時進行的查詢失敗。4.0 版透過使用 TrackedDataInputPlus 包裝訊息串流,捕捉 UnknownCFException,並略過此訊息中的剩餘位元組,來修正此問題。TCP 埠不會關閉,且會保持連線以接收其他訊息。