Cassandra 文件

版本

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

壓縮概觀

什麼是壓縮?

Cassandra 中的資料建立在 記憶表 中。一旦達到記憶體臨界值,資料會寫入 SSTable(一種駐留在磁碟上的 不可變檔案),以再次釋放記憶體。

由於 SSTable 不可變,因此當資料更新或刪除時,舊資料不會被插入或更新覆寫,也不會從 SSTable 中移除。相反地,會建立一個包含更新資料的新 SSTable,並加上新的時間戳記,而舊 SSTable 會標記為刪除。已刪除資料的部分稱為 墓碑

隨著時間推移,Cassandra 可以在不同的 SSTable 中寫入多個版本的列。每個版本可能都有儲存一組獨特欄位,並加上不同的時間戳記。隨著 SSTable 累積,資料的分配可能需要存取越來越多的 SSTable 才能擷取完整的列。

為了保持資料庫的健康,Cassandra 會定期合併 SSTable 並捨棄舊資料。此程序稱為壓縮

為什麼必須執行壓縮?

由於在讀取作業期間會查詢 SSTable,因此保持 SSTable 數量較少非常重要。寫入作業會導致 SSTable 數量增加,因此有必要進行壓縮。除了墓碑問題之外,資料也會因為其他原因而被刪除,例如某些資料的生存期 (TTL) 到期。刪除、更新或過期的資料都是觸發壓縮的有效原因。

壓縮可以達成什麼?

壓縮可以達成的兩個重要因素是效能改善和磁碟空間回收。如果 SSTable 具有必須讀取的重複資料,則讀取作業會較慢。一旦移除墓碑和重複資料,讀取作業就會變快。SSTable 會使用磁碟空間,而透過壓縮減少 SSTable 的大小可以釋放磁碟空間。

壓縮如何運作?

壓縮會對 SSTable 集合進行運作。壓縮會從這些 SSTable 收集每個唯一列的全部版本,並使用列中每個欄位的最新版本(依時間戳記)組成一個完整的列。合併程序的效能很好,因為列會在每個 SSTable 中依據分區金鑰進行排序,而且合併程序不會使用隨機 I/O。每個列的新版本會寫入新的 SSTable。舊版本以及任何準備刪除的列會留在舊的 SSTable 中,並在完成待處理讀取作業後立即刪除。

壓縮類型

壓縮的概念用於 Cassandra 中的不同類型的作業,這些作業的共同點是它會採用一個或多個 SSTable,進行合併,並輸出新的 SSTable。壓縮類型有

次要壓縮

次要壓縮會在 Cassandra 中自動觸發,以執行多項動作

  • 當 SSTable 透過快取新增至節點時

  • 當自動壓縮在停用後啟用時(nodetool enableautocompaction

  • 當壓縮新增新的 SSTable 時

  • 每 5 分鐘檢查一次新的次要壓縮

主要壓縮

當使用者在節點上對所有 SSTable 執行壓縮時,會觸發主要壓縮。

使用者定義的壓縮

與主要壓縮類似,當使用者對特定 SSTable 集合觸發壓縮時,會執行使用者定義的壓縮。

清除

清除會觸發壓縮,以嘗試修復任何損毀的 SSTable。如果資料損毀,這可能會移除有效資料。如果發生這種情況,您需要對節點執行完整修復。

升級 SSTable

當您將 SSTable 升級到最新版本時,就會發生壓縮。在升級到新的主要版本後執行此操作。

清除

壓縮會執行,以移除節點不再擁有的任何範圍。在節點完成引導程式後,通常會在相鄰節點上觸發此類型的壓縮,因為引導程式節點會從這些節點取得某些範圍的所有權。

重建次要索引

如果在節點上重建次要索引,就會觸發壓縮。

反壓縮

修復後,實際修復的範圍會從修復開始時存在的 SSTable 中拆分出來。此類型的壓縮會改寫 SSTable 以完成此任務。

子範圍壓縮

只壓縮給定的子範圍是可行的 - 如果您知道有行為不當的代碼 - 累積許多更新或許多刪除,這個動作會很有用。指令 nodetool compact -st x -et y 會選取包含 x 和 y 之間範圍的所有 SSTable,並對這些 SSTable 發出壓縮。對於大小分層壓縮策略,這很可能會包含所有 SSTable,但對於分層壓縮策略,它可以對 SSTable 的子集發出壓縮。使用 LCS,產生的 SSTable 最終會出現在 L0 中。

策略

有不同的壓縮策略可供使用,以針對不同的工作負載進行最佳化。為您的工作負載選擇正確的壓縮策略,將確保查詢和壓縮本身的最佳效能。

統一壓縮策略 (UCS)

UCS 是大多數工作負載的良好選擇,建議用於新的工作負載。此壓縮策略旨在處理各種工作負載。它旨在能夠處理不可變的時間序列資料和大量的更新和刪除工作負載。它還旨在能夠處理旋轉磁碟和 SSD。

大小分層壓縮策略 (STCS)

STCS 是預設的壓縮策略,因為當其他策略不適合工作負載時,它可用作備援。最適合不嚴格的時間序列工作負載與旋轉磁碟,或當來自 LCS 的 I/O 過高時。

分層壓縮策略 (LCS)

分層壓縮策略 (LCS) 針對讀取密集工作負載或大量更新和刪除的工作負載進行最佳化。它不適合不可變時間序列資料。

時間視窗壓縮策略 (TWCS)

時間視窗壓縮策略專為 TTL、大多數不可變的時間序列資料而設計。

墓碑

什麼是墓碑?

Cassandra 刪除資料的程序旨在改善效能,並與 Cassandra 內建的資料分佈和容錯特性一起使用。

Cassandra 將刪除視為插入,並插入稱為墓碑的時間戳記刪除標記。墓碑會經過 Cassandra 的寫入路徑,並寫入一個或多個節點上的 SSTable。墓碑的主要關鍵特徵差異在於它具有內建的到期日期/時間。在到期期間(寬限期)結束時,墓碑會作為 Cassandra 正常壓縮程序的一部分被刪除。

您也可以使用生存時間 (TTL) 值標記 Cassandra 列或欄。在經過這段時間後,Cassandra 會使用墓碑標記物件,並像處理其他墓碑物件一樣處理它。

為什麼會有墓碑?

墓碑表示物件(列或欄值)已刪除。此方法用於取代移除值,因為 Cassandra 的本質是分散式的。一旦物件被標記為墓碑,查詢將會忽略所有時間戳記早於墓碑插入時間的值。

殭屍

在多節點叢集裡,Cassandra 可能會在兩個或更多節點上儲存相同資料的複本。這有助於防止資料遺失,但會使刪除程序複雜化。如果節點收到要刪除其本地儲存資料的命令,該節點會將指定物件標示為墓碑,並嘗試將墓碑傳遞給包含該物件複本的其他節點。但如果其中一個複本節點在當時沒有回應,它不會立即收到墓碑,因此它仍包含物件的刪除前版本。如果在該節點復原之前,已從叢集的其他部分刪除墓碑物件,Cassandra 會將復原節點上的物件視為新資料,並將其傳播到叢集的其他部分。這種已刪除但仍存在的物件稱為殭屍

寬限期

為了防止殭屍再次出現,Cassandra 會為每個墓碑設定寬限期。墓碑的寬限期會使用資料表屬性 ` WITH gc_grace_seconds` 設定。其預設值為 864000 秒(十天),之後墓碑會過期,並可在壓縮期間刪除。在寬限期過期之前,Cassandra 會在壓縮事件中保留墓碑。每個資料表都可以有自己的這個屬性值。

寬限期的目的是讓沒有回應的節點有時間復原並正常處理墓碑。如果客戶端在寬限期內對墓碑物件寫入新的更新,Cassandra 會覆寫墓碑。如果客戶端在寬限期內傳送該物件的讀取,Cassandra 會忽略墓碑,並在可能的情況下從其他複本中擷取物件。

當沒有回應的節點復原時,Cassandra 會使用暗示性移交來重播節點在停機期間錯過的資料庫變更。Cassandra 期間不會重播墓碑物件的變更。但如果節點在寬限期結束後才復原,Cassandra 可能會錯過刪除。

在墓碑的寬限期結束後,Cassandra 會在壓縮期間刪除墓碑。

刪除

gc_grace_seconds 過期後,墓碑可能會被移除(表示不再有資料的特定部分被刪除)。但刪除的一個複雜之處在於,墓碑可能存在於一個 SSTable 中,而它標記為要刪除的資料在另一個 SSTable 中,因此壓縮也必須移除這兩個 SSTable。更精確地說,刪除實際的墓碑

  • 墓碑必須比 gc_grace_seconds 舊。請注意,即使 gc_grace_seconds 已過期,墓碑也不會在壓縮事件之前被移除。

  • 如果分割區 X 包含墓碑,則包含分割區的 SSTable 加上所有包含資料比包含 X 的墓碑舊的 SSTable 都必須包含在同一個壓縮中。如果任何包含分割區 X 的 SSTable 中的所有資料都比墓碑新,則可以忽略它。

  • 如果啟用選項 only_purge_repaired_tombstones,只有在資料也已修復時才會移除墓碑。此程序在「帶有墓碑的刪除」部分中說明。

如果節點停機或斷線的時間超過 gc_grace_seconds,其已刪除的資料將修復回其他節點,並在叢集中重新出現。這基本上與「沒有墓碑的刪除」部分相同。

無墓碑刪除

想像一個三節點叢集,其中值 [A] 已複製到每個節點。

[A], [A], [A]

如果其中一個節點發生故障,而我們的刪除操作只移除現有值,我們最終可能會得到一個看起來像這樣的叢集

[], [], [A]

然後,修復操作會將值 [A] 替換回缺少該值的兩個節點。

[A], [A], [A]

這將導致我們的資料即使已被刪除,也會像殭屍一樣復活。

有墓碑刪除

再次從一個三節點叢集開始,其中值 [A] 已複製到每個節點。

[A], [A], [A]

如果我們不是移除資料,而是新增一個墓碑物件,那麼單節點故障情況將會像這樣

[A, Tombstone[A]], [A, Tombstone[A]], [A]

現在,當我們發出修復時,墓碑將被複製到副本中,而不是復活已刪除的資料

[A, Tombstone[A]], [A, Tombstone[A]], [A, Tombstone[A]]

我們的修復操作會正確地將系統狀態設定為我們預期的狀態,其中物件 [A] 在所有節點上標記為已刪除。這確實表示我們最終會累積墓碑,而墓碑會永久累積磁碟空間。為了避免永久保留墓碑,我們為 Cassandra 中的每個資料表設定 gc_grace_seconds

完全過期的 SSTable

如果一個 SSTable 只包含墓碑,並且保證該 SSTable 沒有在任何其他 SSTable 中遮蔽資料,則壓縮可以捨棄該 SSTable。如果您看到只包含墓碑的 SSTable(請注意,一旦生存時間到期,TTL 資料就會被視為墓碑),但它沒有被壓縮捨棄,則可能是其他 SSTable 包含較舊的資料。有一個名為 sstableexpiredblockers 的工具,它會列出哪些 SSTable 可以捨棄,以及哪些 SSTable 阻擋它們被捨棄。使用 TimeWindowCompactionStrategy,可以透過啟用 unsafe_aggressive_sstable_expiration 來移除保證(不檢查遮蔽資料)。

TTL

Cassandra 中的資料可以有一個稱為生存時間的附加屬性 - 這用於在時間到期後自動捨棄已過期的資料。一旦 TTL 到期,資料就會轉換成一個墓碑,該墓碑至少會保留 gc_grace_seconds。請注意,如果您將帶有 TTL 的資料與不帶 TTL 的資料(或只是 TTL 長度不同)混合在一起,Cassandra 將很難捨棄所建立的墓碑,因為分割區可能會跨越許多 SSTable,而且並非所有 SSTable 都會同時壓縮。

完全過期的 SSTable

如果一個 SSTable 只包含墓碑,並且保證該 SSTable 沒有在任何其他 SSTable 中遮蔽資料,則壓縮可以捨棄該 SSTable。如果您看到只包含墓碑的 SSTable(請注意,一旦生存時間到期,TTL 資料就會被視為墓碑),但它沒有被壓縮捨棄,則可能是其他 SSTable 包含較舊的資料。有一個名為 sstableexpiredblockers 的工具,它會列出哪些 SSTable 可以捨棄,以及哪些 SSTable 阻擋它們被捨棄。使用 TimeWindowCompactionStrategy,可以透過啟用 unsafe_aggressive_sstable_expiration 來移除保證(不檢查遮蔽資料)。

已修復/未修復資料

使用增量修復時,Cassandra 必須追蹤哪些資料已修復,哪些資料未修復。使用反壓縮時,已修復資料會分割成已修復和未修復的 SSTable。為了避免再次混淆資料,會在兩組資料上執行分開的壓縮策略實例,每個實例只知道已修復或未修復的 SSTable。這表示如果您只執行一次增量修復,然後不再執行,已修復的 SSTable 中可能會存在非常舊的資料,阻礙壓縮在未修復(可能較新)的 SSTable 中刪除墓碑。

資料目錄

由於墓碑和資料可能存在於不同的 SSTable 中,因此了解遺失 SSTable 可能導致資料再次變為活動狀態非常重要,而遺失 SSTable 最常見的方式是硬碟故障。為了避免資料變為活動狀態,墓碑和實際資料始終位於同一個資料目錄中。這樣,如果磁碟遺失,分割區的所有版本都會遺失,且無法取消刪除任何資料。為達成此目的,除了包含已修復/未修復資料的壓縮策略實例外,還會執行每個資料目錄的壓縮策略實例,這表示如果您有 4 個資料目錄,將會執行 8 個壓縮策略實例。這不僅可以避免資料取消刪除,還有其他一些好處

  • 可以並行執行更多壓縮,分層壓縮將有幾個完全分開的層級,每個層級都可以獨立於其他層級執行壓縮。

  • 使用者可以備份和還原單一資料目錄。

  • 不過請注意,目前所有資料目錄都被視為相等,因此如果您有一個小型磁碟和一個大型磁碟作為兩個資料目錄的備份,大型磁碟將受到小型磁碟的限制。解決此問題的方法之一是建立更多由大型磁碟備份的資料目錄。

單一 SSTable 墓碑壓縮

寫入 SSTable 時,會建立一個具有墓碑到期時間的直方圖,並用於嘗試尋找具有大量墓碑的 SSTable,並對該 SSTable 執行單一 SSTable 壓縮,希望能刪除該 SSTable 中的墓碑。在開始此作業之前,還會檢查任何墓碑實際上都能刪除的可能性,以及此 SSTable 與其他 SSTable 重疊的程度。為避免大多數這些檢查,可以啟用壓縮選項 unchecked_tombstone_compaction

一般選項

所有壓縮策略都有許多常見選項;

enabled(預設值:true)

次要壓縮是否應執行。請注意,您可以將「enabled」設為 true 作為壓縮選項,然後執行「nodetool enableautocompaction」以開始執行壓縮。

tombstone_threshold(預設值:0.2)

SSTable 中有多少比例的墓碑讓我們考慮對該 SSTable 執行單一 SSTable 壓縮。

tombstone_compaction_interval(預設值:86400 秒(1 天))

由於在執行單一 SSTable 壓縮時可能無法刪除任何墓碑,因此我們需要確保不會持續重新壓縮某個 SSTable - 此選項說明我們應多久嘗試執行某個 SSTable。

log_all(預設值:false)

新的詳細壓縮記錄,請參閱下方 <detailed-compaction-logging>

unchecked_tombstone_compaction(預設值:false)

單一 SSTable 壓縮有相當嚴格的檢查,以判斷是否應開始執行,此選項會停用這些檢查,某些使用案例可能需要這樣做。請注意,這不會對實際壓縮有任何改變,只有在安全的情況下才會刪除墓碑 - 它可能只會重新寫入 SSTable,而無法刪除任何墓碑。

only_purge_repaired_tombstone(預設值:false)

選項,用於確保只有在資料已修復的情況下才會刪除墓碑,以提高安全性。

min_threshold(預設值:4)

觸發壓縮之前 SSTable 數量的下限。未用於 LeveledCompactionStrategy

max_threshold(預設值:32)

觸發壓縮之前 SSTable 數量的上限。未用於 LeveledCompactionStrategy

此外,請參閱每個策略的區段,以取得特定其他選項。

壓縮 nodetool 指令

nodetool <nodetool> 實用程式提供許多與壓縮相關的指令

enableautocompaction

啟用壓縮。

disableautocompaction

停用壓縮。

setcompactionthroughput

壓縮執行的最大速度 - 預設值為 64MiB/s。

compactionstats

目前和待處理壓縮的統計資料。

compactionhistory

列出最後一次壓縮的詳細資料。

setcompactionthreshold

設定觸發壓縮時 SSTable 數量的最小值/最大值,預設值為 4/32。

使用 JMX 切換壓縮策略和選項

可以使用 JMX 在單一節點上切換壓縮策略及其選項,這是一個在不影響整個叢集的情況下嘗試設定的好方法。mbean 是

org.apache.cassandra.db:type=ColumnFamilies,keyspace=<keyspace_name>,columnfamily=<table_name>

,如果您使用 jconsole 或 jmc,則要變更的屬性為 CompactionParametersCompactionParametersJson。例如,json 版本的語法與您在 ALTER TABLE <alter-table-statement> 陳述式中使用的語法相同

{ 'class': 'LeveledCompactionStrategy', 'sstable_size_in_mb': 123, 'fanout_size': 10}

設定會保留,直到有人執行觸及壓縮設定或重新啟動節點的 ALTER TABLE <alter-table-statement> 為止。

更詳細的壓縮記錄

使用壓縮選項 log_all 啟用,並會在您的記錄目錄中產生更詳細的壓縮記錄檔。