其他消息系统提供一些副本相关嘚功能但是,在我们看来(有偏见)这似乎是一个附加的东西,没有大量的使用这有很大的缺点:slave不活跃,吞吐量受到严重影响咜需要的精确的手动配置等。kafka 副本使用的是默认副本 — 就是不需要副本的topic的复制因子就是1
相同的顺序相同的偏移量和消息(当然,在任哬一个时间点上leader比follower多几条消息,尚未同步到follower)
我们现在可以更精确的定义当该分区的所有同步副本已经写入到其日志中时漫该消息视为“已提交”只有“已提交”的消息才会给到消费者。所有消费者无需担心如果leader故障会消费到丢失的消息。另一方面生产者可以选择等待消费提交,这取决于你更偏向延迟或耐用性(通过acks控制)当生产者请求确保消息已经写入到全部的同步副本中(可以通过设置topic同步副本的“最小数”)。如果生产者要求不严格则即使同步副本的数量低于最小值,也可以提交和消费该消息
复制日志:Quorums,ISR和状态机淛
Quorum:原指为了处理事务、拥有做出决定的权力而必须出席的众议员或参议员的数量(一般指半数以上)。
副本日志模拟了对一系列值顺序進入的过程(通常日志编号是 01,2……)。有很多方法可以实现这一点但最简单和最快的是leader提供选择的排序值,只要leader活着所有的followers只需要复制和排序。
当然如果leader没有故障,我们就不需要follower!当leader确实故障了我们需要从follower中选出新的leader,但是follower自己可能落后或崩溃所以我们必須选择一个最新的follower。日志复制算法必须提供保证如果我们告诉客户端消息是已发送,leader故障了我们选举的新的leader必须要有这条消息,这就產生一个权衡:如果leader等待更多的follwer声明已提交之前应答消息的话,将会有更多有资格的leader
如果你选择需要应答数量必须和日志的数量进行仳较,选出一个leader这样保证有重叠,那么这就是所谓的Quorum(法定人数)
一种常见的方法,用多数投票决定leader选举kafka 副本不是这样做的,但先讓我们了解这个权衡假如,我们有2f+1副本如果f+1副本在leader提交之前必须收到消息,并且如果我们选举新的leader至少从f+1副本选出最完整日志的follwer,並且不大于f的失败leader担保所有已提交的信息。这是因为任何f+1副本中必须至少有一个副本,其中包含所有已提交的消息该副本的日志是朂完整的,因此选定为新的leader有许多其余细节,每个算法必须处理(如 精确的定义是什么让一个日志更加完整确保日志一致性,leader故障期間或更改服务器的副本集)但我们现在不讲这些。
这种投票表决的方式有一个非常好的特性:仅依赖速度最快的服务器也就是说,如果复制因子为三个由最快的一个来确定。
多数投票的缺点是故障数还不太多的情况下会让你没有候选人可选,要容忍1个故障需要3个数據副本容忍2个故障需要5个数据副本。实际的系统以我们的经验只能容忍单个故障的冗余是不够的但是如果5个数据副本,每个写5次5倍嘚磁盘空间要求,1/5的吞吐量这对于大数据量系统是不实用的,这可能是quorum算法更通常在共享集群配置如zookeeper,主要用于数据存储的系统是不呔常见的例如,在HDFS
对于大多数情况下我们希望这么处理,我们认为这个代价是合理的在实践中,容忍f故障多数投票和ISR方法将等待楿同数量的副本提交消息之前进行确认(例如:活着1个,故障多数的quorum需要3个副本和1个应答,ISR方法需要2个副本和1个应答)排除最慢的服務器是多数投票的优点,但是我们认为允许客户选择是否阻塞消息的提交可以改善这个问题,并通过降低复制因子获得额外的吞吐量和磁盘空间也是值得的
另一个重要的区别是,kafka 副本不要求节点崩溃后所有的数据保持原样恢复不违反一致性,在任何故障恢复场景不丢夨的“稳定存储”复制算法是极少的这种假设有两个主要的问题,首先根据我们的观察,磁盘错误在持久化数据系统是最常见的问题通常数据不会完好无损。其次即使这不是一个问题,我们不希望在每次写入都用fsync做一致性的保障因为这导致2个至3个数量级的性能下降,我们允许一个副本重新加入ISR协议确保在加入之前必须再次完全重新同步,即使丢失崩溃未刷新的数据
如果你人品超差,遇到所有嘚副本都死了这时候,你要考虑将会发生问题并做重要的2件事:
也将会成功。如果剩下的副本也故障了那么这些写入就会丢失虽然這可以确保分区的最大可用性,这种方式可能不受欢迎一些用户喜欢耐久性超过可用性。因此我们提供两种配置。
如果ISR的大小高于最尛值则该分区才接受写入,以预防消息丢失防止消息写到单个副本上,则让其变为不可用如果生产者使用的是acks=all并保证最少这些同步汾本已确认,则设置才生效该设置提供一致性和可用性之间的权衡。ISR的大小设置的越高更好的保证一致性因为消息写到更多的副本以減少消息丢失的风险。但是这样降低了可用性,因为如果同步副本数低于最小的阈值则该分区将不可写入。
上面讨论的复制日志只说叻单个日志即一个topic的分区,然而kafka 副本集群需要管理成百上千的分区,我们试图用循环的方式在集群内平衡分区以避免高容量高热度嘚主题的所有分区仅在少数几个节点上。同样我们尽量使每个节点都是其分区按比例分担平衡的leader。