修復
Cassandra 旨在在其中一個節點關閉或無法連線時保持可用。但是,當節點關閉或無法連線時,它最終需要找出它錯過的寫入。提示會嘗試通知節點錯過的寫入,但盡力而為,並不保證會通知節點錯過的寫入 100%。這些不一致最終可能會導致資料遺失,因為節點被取代或墓碑到期。
這些不一致性會透過修復程序修復。修復會透過比較節點各自資料集的共同代幣範圍,並串流節點之間不同步區段的差異,來同步節點之間的資料。它會使用 Merkle 樹比較資料,Merkle 樹是雜湊層級。
增量修復和完整修復
有 2 種類型的修復:完整修復和增量修復。完整修復會針對要修復的代幣範圍中的所有資料進行操作。增量修復只會修復自上次增量修復以來寫入的資料。
增量修復是預設的修復類型,如果定期執行,可以大幅減少執行修復的時間和 I/O 成本。但是,了解一旦增量修復將資料標記為已修復,就不會再嘗試再次修復它,這一點很重要。對於同步錯過的寫入來說,這很好,但無法防止磁碟損毀、操作員錯誤導致資料遺失或 Cassandra 中的錯誤等問題。因此,仍應偶爾執行完整修復。
使用方式和最佳實務
由於修復可能會導致大量磁碟和網路 I/O,因此 Cassandra 沒有自動執行。它是由操作員透過 nodetool 執行的。
增量修復是預設值,並使用下列指令執行
nodetool repair
可以使用下列指令執行完整修復
nodetool repair --full
此外,可以在單一鍵值空間上執行修復
nodetool repair [options] <keyspace_name>
甚至可以在特定表格上執行
nodetool repair [options] <keyspace_name> <table1> <table2>
修復指令僅會修復正在修復的節點上的令牌範圍;它不會修復整個叢集。預設情況下,修復會針對節點上複製的所有令牌範圍執行,在每個節點上執行時會造成重複工作。使用 -pr
旗標僅修復節點上的「主要」範圍,以避免重複工作。在叢集中的每個資料中心中的每個節點上執行 nodetool repair -pr
指令,直到所有節點和資料中心都修復完畢,以執行完整叢集修復。
當然,適合叢集的特定修復頻率取決於多個因素。但是,如果您剛開始使用並正在尋找起點,那麼每 1-3 天執行一次增量修復,每 1-3 週執行一次完整修復可能是合理的。如果您不想執行增量修復,那麼每 5 天執行一次完整修復是一個不錯的起點。
至少應執行修復的頻率應足夠,以確保 GC 寬限期永遠不會在未修復的資料上到期。否則,已刪除的資料可能會重新出現。在 GC 寬限期預設為 10 天的情況下,至少每 7 天修復叢集中的每個節點一次,將可防止這種情況發生,同時提供足夠的餘裕來允許延遲。
其他選項
-pr, --partitioner-range
-
將修復限制為正在修復的節點的「主要」令牌範圍。主要範圍只是一個令牌範圍,節點是環中的第一個複本。
-prv, --preview
-
估計給定修復指令會發生的串流量。這會建立梅克爾樹並列印預期的串流活動,但實際上不會執行任何串流。預設情況下,會估計增量修復,新增
--full
旗標以估計完整修復。 -vd, --validate
-
驗證修復後的資料在所有節點上是否相同。與
--preview
類似,這會建立並比較修復後資料的梅克爾樹,但不會執行任何串流。這對於進行疑難排解很有用。如果這顯示修復後的資料不同步,則應執行完整修復。
nodetool 修復文件 <nodetool_repair>
完整修復範例
在增加鍵值空間的複本係數或將節點新增到叢集後,通常需要完整修復才能重新分配資料。完整修復涉及串流 SSTable。要示範完整修復,請從三個節點的叢集開始。
[ec2-user@ip-10-0-2-238 ~]$ nodetool status
Datacenter: us-east-1
=====================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
-- Address Load Tokens Owns Host ID Rack
UN 10.0.1.115 547 KiB 256 ? b64cb32a-b32a-46b4-9eeb-e123fa8fc287 us-east-1b
UN 10.0.3.206 617.91 KiB 256 ? 74863177-684b-45f4-99f7-d1006625dc9e us-east-1d
UN 10.0.2.238 670.26 KiB 256 ? 4dcdadd2-41f9-4f34-9892-1f20868b27c7 us-east-1c
建立一個具有複製因子 3 的鍵空間
cqlsh> DROP KEYSPACE cqlkeyspace;
cqlsh> CREATE KEYSPACE CQLKeyspace
... WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 3};
將表格新增到鍵空間
cqlsh> use cqlkeyspace;
cqlsh:cqlkeyspace> CREATE TABLE t (
... id int,
... k int,
... v text,
... PRIMARY KEY (id)
... );
新增表格資料
cqlsh:cqlkeyspace> INSERT INTO t (id, k, v) VALUES (0, 0, 'val0');
cqlsh:cqlkeyspace> INSERT INTO t (id, k, v) VALUES (1, 1, 'val1');
cqlsh:cqlkeyspace> INSERT INTO t (id, k, v) VALUES (2, 2, 'val2');
查詢會列出新增的資料
cqlsh:cqlkeyspace> SELECT * FROM t;
id | k | v
----+---+------
1 | 1 | val1
0 | 0 | val0
2 | 2 | val2
(3 rows)
對三節點叢集進行下列變更
-
將複製因子從 3 增加到 4。
-
將第 4 個節點新增到叢集
當複製因子增加時,會輸出下列訊息,表示需要根據 (CASSANDRA-13079) 進行完整修復
cqlsh:cqlkeyspace> ALTER KEYSPACE CQLKeyspace
... WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 4};
Warnings :
When increasing replication factor you need to run a full (-full) repair to distribute the
data.
使用下列指令對鍵空間 cqlkeyspace
表格 t
執行完整修復
nodetool repair -full cqlkeyspace t
完整修復在約一秒內完成,如輸出所示
[ec2-user@ip-10-0-2-238 ~]$ nodetool repair -full cqlkeyspace t
[2019-08-17 03:06:21,445] Starting repair command #1 (fd576da0-c09b-11e9-b00c-1520e8c38f00), repairing keyspace cqlkeyspace with repair options (parallelism: parallel, primary range: false, incremental: false, job threads: 1, ColumnFamilies: [t], dataCenters: [], hosts: [], previewKind: NONE, # of ranges: 1024, pull repair: false, force repair: false, optimise streams: false)
[2019-08-17 03:06:23,059] Repair session fd8e5c20-c09b-11e9-b00c-1520e8c38f00 for range [(-8792657144775336505,-8786320730900698730], (-5454146041421260303,-5439402053041523135], (4288357893651763201,4324309707046452322], ... , (4350676211955643098,4351706629422088296]] finished (progress: 0%)
[2019-08-17 03:06:23,077] Repair completed successfully
[2019-08-17 03:06:23,077] Repair command #1 finished in 1 second
[ec2-user@ip-10-0-2-238 ~]$
nodetool tpstats
指令應列出已完成的修復,其中 修復任務
> 已完成
欄位值為 1
[ec2-user@ip-10-0-2-238 ~]$ nodetool tpstats
Pool Name Active Pending Completed Blocked All time blocked
ReadStage 0 0 99 0 0
…
Repair-Task 0 0 1 0 0
RequestResponseStage 0 0 2078 0 0