Kafka在可配置数量的服务器上复制每个主题分区的日志(您可以逐个主题地设置此复制因子)。这允许在群集中的服务器发生故障时自动故障转移到这些副本,以便在出现故障时消息仍然可用。
其他消息传递系统提供了一些与复制相关的功能,但是在我们的看法中,这似乎是一个tacked-on的东西,没有大量使用,并且有很大的缺点:副本处于非活动状态,吞吐量受到严重影响,需要手动配置等。Kafka默认情况下用于复制 - 事实上,我们将不复制的主题实现为复制因子为1的复制主题。
复制单元是主题分区。在非故障情况下,Kafka中的每个分区都有一个leader和零个或多个followers。包括leader在内的副本总数构成复制因子。所有读写都将转到分区的leader。通常,有比broker数多得多的分区,leader在broker之间平均分配。follower的日志与leader的日志相同 - 所有日期都具有相同的偏移量和相同顺序的消息(当然,在任何给定时间,leader可能在其日志末尾有一些尚未复制的消息)。
follower像正常的Kafka消费者一样消费来自leader的消息并将其应用于他们自己的日志中。让follower从leader中pull出来具有很好的特性,允许follower将它们正在应用的日志自然的batch在一起。
与大多数分布式系统一样,自动处理故障需要准确定义节点“活着”的含义。对于Kafka节点,活跃度有两个条件:
我们将满足这两个条件的节点称为“同步中”以避免“活着”或“失败”的模糊性。leader跟踪“同步中”节点的集合。如果follower死亡,卡住或落后,领导者将从同步副本列表中删除它。卡住和滞后复制品的确定由replica.lag.time.max.ms配置控制。
在分布式系统术语中,我们只尝试处理故障的“故障/恢复”模型,其中节点突然停止工作,然后恢复(可能不知道它们已经死亡)。 Kafka没有处理产生任意或恶意的响应(可能是由于错误或foul play)节点中所谓的“ Byzantine”故障。
现在,我们可以更精确地定义,当该分区的所有同步副本将消息应用于其日志时,将消息视为已提交。只有已提交的消息才会发给消费者。这意味着消费者不必担心如果leader失败可能会丢失可能丢失的消息。另一方面,生产者可以选择是否等待消息的发送,这取决于他们在延迟和持久性之间进行的权衡。请注意,主题具有同步副本“最小数量”的设置,当生产者请求确认已将消息写入完整的同步副本集时,将检查该副本。如果生产者请求不那么严格的确认,则即使同步副本的数量低于最小值(例如,它可以仅低于领导者),也可以提交和消费该消息。
Kafka提供的保证是,只要始终存在至少一个同步副本,就不会丢失已提交的消息。
在短暂的故障转移期后,Kafka将在出现节点故障时仍然可用,但在网络分区存在时可能无法保持可用状态。
Kafka分区的核心是复制日志。复制日志是分布式数据系统中最基本的原语之一,有许多实现方法。其他系统可以使用复制日志作为基元,以实现状态机样式中的分布式系统。复制日志模拟了一系列有序进入消费者进行处理的过程。有很多方法可以实现这一点,但最简单和最快的方法是让领导者选择提供给它的值的顺序。只要leader还活着,所有follower都需要只复制值并跟随leader的选择。
当然,如果leader没有失败,我们就不需要follower了!当leader死亡时,我们需要从follower中选择一位新的leader。但是follower本身可能落后或崩溃所以我们必须确保我们选择一个最新的follower。日志复制算法必须提供的基本保证是,如果我们告诉客户端消息已提交,并且leader失败,我们选择的新leader也必须拥有该消息。这产生了一个权衡:如果leader在宣布提交之前等待更多的follower提交消息,那么将会有更多潜在的可选leader。
如果您选择所需的确认数量和必须比较的日志数量以选择leader以确保重叠,那么这称为仲裁(Quorum)。