修复
Cassandra 被设计为即使其中一个节点出现故障或无法访问也能保持可用。但是,当节点出现故障或无法访问时,它最终需要发现它错过的写入。提示尝试通知节点错过的写入,但它们是尽力而为的,不能保证通知节点 100% 的错过的写入。这些不一致最终会导致数据丢失,因为节点被替换或墓碑过期。
这些不一致通过修复过程来解决。修复通过比较节点各自数据集的公共令牌范围并流式传输节点之间任何不同步部分的差异来同步节点之间的数据。它使用默克尔树比较数据,默克尔树是哈希的层次结构。
增量修复和完整修复
修复有两种类型:完整修复和增量修复。完整修复对要修复的令牌范围内的所有数据进行操作。增量修复仅修复自上次增量修复以来写入的数据。
增量修复是默认的修复类型,如果定期运行,可以显着减少执行修复的时间和 IO 成本。但是,重要的是要了解,一旦增量修复将数据标记为已修复,它就不会再尝试修复它。这对于同步错过的写入来说很好,但它不能防止磁盘损坏、操作员错误导致的数据丢失或 Cassandra 中的错误。因此,仍然应该偶尔运行完整修复。
用法和最佳实践
由于修复会导致大量的磁盘和网络 IO,因此 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 宽限期永远不会过期。否则,已删除的数据可能会重新出现。使用默认的 10 天 GC 宽限期,至少每 7 天修复一次集群中的每个节点将防止这种情况,同时提供足够的余量来容忍延迟。
其他选项
-pr, --partitioner-range
-
将修复限制为正在修复的节点的“主”令牌范围。主范围只是节点在环中作为第一个副本的令牌范围。
-prv, --preview
-
估计给定修复命令将发生的流式传输量。这将构建默克尔树并打印预期的流式传输活动,但不会实际执行任何流式传输。默认情况下,会估计增量修复,添加
--full
标志来估计完整修复。 -vd, --validate
-
验证已修复的数据在所有节点上是否相同。类似于
--preview
,这将构建和比较已修复数据的默克尔树,但不会执行任何流式传输。这对于故障排除很有用。如果这表明已修复的数据不同步,则应运行完整修复。
nodetool repair docs <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。
-
将第四个节点添加到集群
当复制因子增加时,将输出以下消息,指示需要完整修复,如 (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
命令应列出已完成的修复,Repair-Task
> Completed
列值为 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