前天,我使用下面的命令对一个表的5节点cassandra集群中的一个节点进行了完整的顺序修复。
nodetool repair -full -seq -tr <keyspace> <table> > <logfile>
现在,发出命令的节点已正确修复,这可以从下面的命令中推断出来
nodetool cfstats -H <keyspace.columnFamily>
但是,对于其他节点也不能这样说,因为对于它们,我得到了一个随机值repair%,明显更小。
我不确定这里发生了什么,看起来唯一为keyspace和column家族修复的节点是发出修复命令的节点。对这里可能发生的事情有什么猜测,或者如何正确地调查这个问题
谢谢!
1条答案
按热度按时间iyfamqjs1#
您说过您的集群有5个节点,但不是表中使用的复制因子(rf)——我假设您使用的是公共rf=3。当rf=3时,每条数据在5个节点上复制3次。
您遗漏的关键点是,在这样的设置中,每个特定节点并不包含所有数据。它包含了多少数据?让我们做一些简单的数学:如果插入到表中的实际数据量是x,那么集群存储的数据总量是3x(因为rf=3,每个数据段有三个副本)。这个总数分布在5个节点上,因此每个节点将保持(3x)/5,即3/5x。
当您在一个特定节点上开始修复时,它只修复该节点拥有的数据,即,正如我们刚才计算的,总数据的3/5。此修复所做的是针对此节点所保存的每一条数据,将此数据与其他副本所保存的副本进行比较,修复不一致性并修复所有这些副本。这意味着当修复结束时,在我们修复的节点中,它的所有数据都被修复。但是对于其他节点,并不是所有的数据都被修复了——只是与发起修复的节点相交的部分。这个交集应该大约是数据的3/53/5或36%(当然所有数据都是随机分布的,所以你可能会得到一个接近36%的数字,但不完全是36%)。
因此,您现在可能已经意识到,这意味着“nodetool repair”不是集群范围的操作。如果在一个节点上启动,则只能保证修复一个节点上的所有数据,而在其他节点上修复的数据可能较少。因此,必须分别在每个节点上运行修复。
现在您可能会问:既然修复节点1也修复了节点2的36%,那么同样修复节点2会不会是一种浪费,因为我们已经完成了36%的工作?的确,这是一种浪费。所以cassandra有一个修复选项“-pr”(“主范围”),它确保每个数据块的3个副本中只有一个会修复它。当rf=3时,“nodetool repair-pr”比没有“-pr”时快三倍;您仍然需要在每个节点上分别运行它,当所有节点完成时,您的数据将在所有节点上得到100%的修复。
所有这些都相当不方便,而且在长时间的维修过程中很难从瞬时故障中恢复。这就是为什么来自datastax和scylladb的商业cassandra产品都提供了一个单独的修复工具,它比“nodetool repair”更方便,确保以最有效的方式修复整个集群,并从暂时的问题中恢复,而不必从头开始重复冗长的修复过程。