在 Apache Cassandra 中定義和最佳化資料分割槽

Anil Inamdar發表於2022-11-27

速度和可擴充套件性是 Apache Cassandra 不變的追求;來學習一下如何充分發揮它的專長吧。

在 Apache Cassandra 中定義和最佳化資料分割槽

Apache Cassandra 是一個資料庫,但又不是一個簡單的資料庫;它是一個複製資料庫,專為可擴充套件性、高可用性、低延遲和良好效能而設計調整。Cassandra 可以幫你的資料在區域性中斷、硬體故障時,以及很多管理員認為資料量過多的情況下倖免於難。

全面掌握資料分割槽知識,你就能讓 Cassandra 叢集實現良好的設計、極高的效能和可擴充套件性。在本文中,我將探究如何定義分割槽,Cassandra 如何使用這些分割槽,以及一些你應該瞭解的最佳實踐方案和已知問題。

基本概念是這樣的: 供資料庫關鍵函式(如資料分發、複製和索引化)使用的原子單元,單個這樣的資料塊就是一個分割槽。分散式資料系統通常會把傳入的資料分配到這些分割槽中,使用簡單的數學函式(例如 identity 或 hashing 函式)執行分割槽過程,並用得到的 “分割槽鍵” 對資料分組,進一步再形成分割槽。例如,假設傳入資料是伺服器日誌,使用 “identity” 分割槽函式和每個日誌的時間戳(四捨五入到小時值)作為分割槽鍵,我們可以對這些資料進行分割槽,實現每個分割槽各儲存一小時的日誌的目的。

Cassandra 中的資料分割槽

Cassandra 作為分散式系統執行,並且符合前述資料分割槽原則。使用 Cassandra,資料分割槽依賴於在叢集級別配置的演算法和在表級別配置的分割槽鍵。

Cassandra data partition

Cassandra 查詢語言(CQL)使用大家很熟悉的 SQL 表、行、列等術語。在上面的示例圖中,表配置的主鍵中包含了分割槽鍵,具體格式為:主鍵Primary Key = 分割槽鍵Partition Key + [聚簇列Clustering Columns] 。

Cassandra 中的主鍵既定義了唯一的資料分割槽,也包含著分割槽內的資料排列依據資訊。資料排列資訊取決於聚簇列(非必需項)。每個唯一的分割槽鍵代表著伺服器(包括其副本所在的伺服器)中管理的若干行。

在 CQL 中定義主鍵

接下來的四個示例演示瞭如何使用 CQL 語法表示主鍵。定義主鍵會讓資料行分到不同的集合裡,通常這些集合就是分割槽。

定義方式 1(分割槽鍵:log_hour,聚簇列:無)

CREATE TABLE server_logs(
   log_hour TIMESTAMP PRIMARYKEY,
   log_level text,
   message text,
   server text
   )

這裡,有相同 log_hour 的所有行都會進入同一個分割槽。

定義方式 2(分割槽鍵:log_hour,聚簇列:log_level)

CREATE TABLE server_logs(
   log_hour TIMESTAMP,
   log_level text,
   message text,
   server text,
   PRIMARY KEY (log_hour, log_level)
   )

此定義方式與方式 1 使用了相同的分割槽鍵,但此方式中,每個分割槽的所有行都會按 log_level 升序排列。

定義方式 3(分割槽鍵:log_hour,server,聚簇列:無)

CREATE TABLE server_logs(
   log_hour TIMESTAMP,
   log_level text,
   message text,
   server text,
   PRIMARY KEY ((log_hour, server))
   )

在此定義中,server 和 log_hour 欄位都相同的行才會進入同一個分割槽。

定義方式 4(分割槽鍵:log_hour,server,聚簇列:log_level)

CREATE TABLE server_logs(
   log_hour TIMESTAMP,
   log_level text,
   message text,
   server text,
   PRIMARY KEY ((log_hour, server),log_level)
   )WITH CLUSTERING ORDER BY (column3 DESC);

此定義方式與方式 3 分割槽相同,但分割槽內的行會依照 log_level 降序排列。

Cassandra 如何使用分割槽鍵

Cassandra 依靠分割槽鍵來確定在哪個節點上儲存資料,以及在需要時定位資料。Cassandra 透過檢視錶中的分割槽鍵來執行這些讀取和寫入操作,並使用令牌tokens(一個 -2^{63} 到 +2^{63}-1 範圍內的 long 型別值)來進行資料分佈和索引。這些令牌透過分割槽器對映到分割槽鍵,分割槽器使用了將分割槽鍵轉換為令牌的分割槽函式。透過這種令牌機制,Cassandra 叢集的每個節點都擁有一組資料分割槽。然後分割槽鍵在每個節點上啟用資料索引。

Cassandra cluster with 3 nodes and token-based ownership

圖中顯示了一個三節點的 Cassandra 叢集以及相應的令牌範圍分配。這只是一個簡單的示意圖:具體實現過程使用了 Vnodes

資料分割槽對 Cassandra 叢集的影響

用心的分割槽鍵設計對於實現用例的理想分割槽大小至關重要。合理的分割槽可以實現均勻的資料分佈和強大的 I/O 效能。分割槽大小對 Cassandra 叢集有若干需要注意的影響:

  • 讀取效能 —— 為了在磁碟上的 SSTables 檔案中找到分割槽,Cassandra 使用快取、索引和索引摘要等資料結構。過大的分割槽會降低這些資料結構的維護效率,從而對效能產生負面影響。Cassandra 新版本在這方面取得了長足的進步:特別是 3.6 及其以上版本的 Cassandra 引擎引入了儲存改進,針對大型分割槽,可以提供更好的效能,以及更強的應對記憶體問題和崩潰的彈性。
  • 記憶體使用 —— 大分割槽會對 JVM 堆產生更大的壓力,同時分割槽的增大也降低了垃圾收集機制的效率。
  • Cassandra 修復 —— 大分割槽使 Cassandra 執行修復維護操作(透過跨副本比較資料來保持資料一致)時更加困難。
  • “墓碑”刪除 —— 聽起來可能有點駭人,Cassandra 使用稱為“墓碑tombstones”的獨特標記來記錄要刪除的資料。如果沒有合適的資料刪除模式和壓縮策略,大分割槽會使刪除過程變得更加困難。

雖然這些影響可能會讓人更傾向於簡單地設計能產生小分割槽的分割槽鍵,但資料訪問模式對理想的分割槽大小也有很大影響(有關更多資訊,請閱讀關於 Cassandra 資料建模 的深入講解)。資料訪問模式可以定義為表的查詢方式,包括表的所有 select 查詢。 理想情況下,CQL 選擇查詢應該在 where 子句中只使用一個分割槽鍵。也就是說,當查詢可以從單個分割槽,而不是許多較小的分割槽獲取所需資料時,Cassandra 是最有效率的。

分割槽鍵設計的最佳實踐

遵循分割槽鍵設計的最佳實踐原則,這會幫你得到理想的分割槽大小。根據經驗,Cassandra 中的最大分割槽應保持在 100MB 以下。理想情況下,它應該小於 10MB。雖然 Cassandra 3.6 及其以上版本能更好地支援大分割槽,但也必須對每個工作負載進行仔細的測試和基準測試,以確保分割槽鍵設計能夠支援所需的叢集效能。

具體來說,這些最佳實踐原則適用於任何分割槽鍵設計:

  • 分割槽鍵的目標必須是將理想數量的資料放入每個分割槽,以支援其訪問模式的需求。
  • 分割槽鍵應禁止無界分割槽:那些大小可能隨著時間無限增長的分割槽。例如,在上面的 server_logs 示例中,隨著伺服器日誌數量的不斷增加,使用伺服器列作為分割槽鍵就會產生無界分割槽。相比之下,使用 log_hour 將每個分割槽限制為一個小時資料的方案會更好。
  • 分割槽鍵還應避免產生分割槽傾斜,即分割槽增長不均勻,有些分割槽可能隨著時間的推移而不受限制地增長。在 server_logs 示例中,在一臺伺服器生成的日誌遠多於其他伺服器的情況下使用伺服器列會產生分割槽傾斜。為了避免這種情況,可以從表中引入另一個屬性來強制均勻分佈,即使要建立一個虛擬列來這樣做,也是值得的。
  • 使用時間元素和其他屬性的組合分割槽鍵,這對時間序列資料分割槽很有幫助。這種方式可以防止無界分割槽,使訪問模式能夠在查詢特定資料時使用時間屬性,而且能夠對特定時間段內的資料進行刪除。上面的每個示例都使用了 log_hour 時間屬性來演示這一點。

還有一些工具可用於幫助測試、分析和監控 Cassandra 分割槽,以檢查所選模式是否高效。透過仔細設計分割槽鍵,使解決方案的資料和需求保持一致,並遵循最佳實踐原則來最佳化分割槽大小,你就可以充分利用資料分割槽,更好地發揮 Cassandra 的可擴充套件性和效能潛力。


via: https://opensource.com/article/20/5/apache-cassandra

作者:Anil Inamdar 選題:lujun9972 譯者:unigeorge 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出

相關文章