您说您的集群有 5 个节点,但不是您为表使用的复制因子(RF) - 我假设您使用了常见的 RF=3。当 RF=3 时,每条数据在五个节点上复制 3 次。
您错过的关键点是,在这样的设置中,每个特定节点都不包含所有数据。它包含多少总数据?我们做一些简单的数学运算:如果实际插入表的数据量是 X,那么集群存储的数据总量是 3*X(由于 RF=3,每条数据有 3 个副本)。这个总数分布在 5 个节点上,因此每个节点将持有 (3*X)/5,即 3/5*X。
当您在一个特定节点上开始修复时,它只修复该节点拥有的数据,即,正如我们刚刚计算的那样,是总数据的 3/5。此修复所做的是针对该节点持有的每条数据,它将这些数据与其他副本持有的副本进行比较,修复不一致并修复所有这些副本。这意味着当修复结束时,在我们修复的节点中,它的所有数据都被修复了。但是对于其他节点,并不是所有的数据都被修复了——只是与启动修复的节点相交的部分。这个交集应该是大约 3/5*3/5 或 36% 的数据(当然,一切都是随机分布的,所以你可能会得到一个接近 36% 但不完全是 36% 的数字)。
所以你现在可能已经意识到,这意味着“nodetool repair”不是集群范围的操作。如果在一个节点上启动,只能保证修复一个节点上的所有数据,可能在其他节点上修复较少。因此,您必须分别在每个节点上运行修复。
现在你可能会问:既然修复节点 1 也修复了节点 2 的 36%,那么既然我们已经完成了 36% 的工作,那么修复节点 2 岂不是很浪费?的确,这是一种浪费。所以 Cassandra 有一个修复选项“-pr”(“primary range”),它确保每个数据的 3 个副本中只有一个会修复它。使用 RF=3,“nodetool repair -pr”将比没有“-pr”快三倍;您仍然需要在每个节点上单独运行它,当所有节点完成时,您的数据将在所有节点上 100% 修复。
所有这些都相当不方便,而且在长时间的维修过程中也很难从短暂的故障中恢复。这就是为什么来自 Datastax 和 ScyllaDB 的两个商业 Cassandra 产品都提供了一个单独的修复工具,它比“nodetool repair”更方便,确保以最有效的方式修复整个集群,并在没有临时问题的情况下恢复从头开始重做漫长的修复过程。