改進的節點間訊息傳遞
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
衡量。同時實施三個獨立的限制,以確保在任何合理的故障組合影響節點穩定性的情況下,都能持續進度。
-
對排隊傳送至其他節點的訊息,以及等待從叢集中的其他節點到達後處理的訊息,實施整體、每個端點和每個連線的限制。這些限制套用於傳送或接收訊息的線上大小。
-
在實施任何端點或整體限制之前,會孤立地消耗基本每個連結限制。每個節點對有三個連結:緊急、小和大型。任何給定的節點最多可以有
N*3 * (internode_application_send_queue_capacity 以位元組為單位 + internode_application_receive_queue_capacity 以位元組為單位)
的訊息資料排隊,而不會在它們之間進行任何協調,儘管在實際上,使用具備代幣感知的路由時,只有 RF*tokens 節點需要以顯著的頻寬進行通訊。 -
每個端點限制會同時與整體限制,對叢集中單一節點的所有連結實施在超過每個連結限制的所有訊息上。整體限制會同時與每個端點限制,對叢集中任何節點的所有連結實施在超過每個連結限制的所有訊息上。已將下列設定新增至
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 或欄位未知),則會略過位元組,而不會中斷整個連線並遺失所有緩衝訊息。會立即將失敗原因傳送回協調節點,而不是等到協調節點的回呼過期。此邏輯已延伸至損毀的框架;損毀的框架會安全略過,而不會中斷連線。
接收路徑對記憶體使用量實施嚴格限制。具體來說,所有已剖析但未處理訊息所佔用的記憶體都受到限制,依據每個連線、每個端點和整體為基礎。一旦連線超過其本機未處理容量,且無法從每個端點和整體保留區借用任何許可,便會停止處理更多訊息,提供自然的背壓,直到重新獲得足夠的容量。
新增訊息大小限制
Cassandra pre-4.0 無法保護伺服器,以免為節點間訊息物件配置過大的緩衝區。新增訊息大小限制有助於處理問題,例如故障叢集參與者。4.0 版引入了最大訊息大小設定參數,類似於最大變異大小 - 預設設定為保留端點容量。
在反序列化節點間訊息時,從未知資料表中復原
如 (CASSANDRA-9289) 中所述,從其他節點的訊息中看到未知資料表時,能順利復原會很好。在 4.0 版之前,我們會關閉連線並重新連線,這可能會導致其他同時進行的查詢失敗。4.0 版透過使用 TrackedDataInputPlus
包裝訊息串流,捕捉 UnknownCFException
,並略過此訊息中的剩餘位元組,來修正此問題。TCP 埠不會關閉,且會保持連線以接收其他訊息。