kafka如何保证高可用
- 多副本机制:Kafka 通过多副本机制来提高数据的可靠性和可用性。每个分区(topic partition)可以配置多个副本(replica),这些副本分布在不同的 broker 上,当其中某个 broker 发生故障时,其他 broker 上的副本可以继续提供服务。
- ISR 机制:Kafka 针对多副本机制提出了 ISR(in-sync replicas)的概念。ISR 中的副本与分区领导者(leader)保持同步,它们都会接收并确认已提交的消息,从而更新其自己的高水位(high watermark)。只有当ISR中所有副本的高水位保持一致时,才能保证数据不会丢失或重复消费。当ISR中的某个副本出现故障时,Kafka 会从 ISR 中选举一个新的副本作为新的分区领导者,从而确保服务的可用性。
- Controller 机制:Kafka 的 Controller 是一个特殊的 broker,负责管理整个 Kafka 集群的元数据(metadata)。当某个 broker 发生故障时,Controller 会检测并处理故障节点,并协调其他 broker 上的副本进行重新分配,从而保证服务的可用性。
- 快速恢复机制:Kafka 的多副本机制和 ISR 机制可以保证数据的可靠性和一致性,但当某个 broker 发生故障时,重新选举新的分区领导者需要一定的时间。为了缩短服务恢复的时间,Kafka 引入了快速恢复机制,它可以让 ISR 中的副本尽快成为新的分区领导者,从而减少服务的停机时间。
综合上述机制,Kafka 可以提供高可用的消息服务,即使发生节点故障也不会导致数据丢失或服务中断。
kafka如何保证数据有序
针对消息有序的业务需求,分为全局有序和局部有序。
- 全局有序:一个Topic下的所有消息都需要按照生产顺序消费。
- 局部有序:一个Topic下的消息,只需要满足同一业务字段的要按照生产顺序消费。例如:Topic消息是订单的流水表,包含订单orderId,业务要求同一个orderId的消息需要按照生产顺序进行消费。
全局有序
由于kafka的一个topic可以分为多个partition,producer发送消息的时候,是分布在不同的partition的。当produrer发送消息是按顺序的,partition内也是按顺序的,但是不确定分布在那个partition,会导致消息顺序混乱。
如果要保证全局有序,只能指定一个partition。
而且对应的consumer也要使用单线程或者保证消费顺序的线程模型,否则也会因为多个线程之间的调度顺序问题,导致消费乱序
局部有序
可以在发送到kafka时,指定Partition Key,kafka会对齐进行hash计算,同一个key的的消息会分到同一个partition。此时partition也可以设置多个,提升吞吐量。
如下图所示,在不增加partition数量的情况下想提高消费速度,可以考虑再次hash唯一标识(例如订单orderId)到不同的线程上,多个消费者线程并发处理消息(依旧可以保证局部有序)。
消息重试对顺序消息的影响
对于有先后顺序的消息,A,B,正常情况下应该是A先发送完以后再发送B,但是在异常情况下,A发送失败,但是B发送成功,这时候消费顺序就变成了BA。
因此严格的顺序消费还需要指定,max.in.flight.requests.per.connection
参数。
参数指定了生产者在收到服务器响应之前可以发送多少个消息。它的值越高,就会占用越多的内存,同时也会提升吞吐量。把它设为1就可以保证消息是按照发送的顺序写入服务器的。
此外,对于某些业务场景,设置max.in.flight.requests.per.connection
=1会严重降低吞吐量,如果放弃使用这种同步重试机制,则可以考虑在消费端增加失败标记的记录,然后用定时任务轮询去重试这些失败的消息并做好监控报警。
kafka如何保证数据不丢失
将生产者将数据发送到broker以后,broker会返回给生产端一个ack确认,在kafka中,主要有三种ack方案
生产端
-
acks:0 这种方案中,生产者只需要发送即可,不需要等待返回,这种方式的吞吐量最大,但是如果broker挂掉的话会丢失数据,一般只用于日志收集等场景
-
acks:1 在这种方案中,生产者发送数据到broker后,master副本接受到消息后,就会返回成功,这种方案是默认的ack方案,如果master ack后,但是挂掉了,副本还未同步,还是会有丢失数据的可能。
-
acks:-1 在这种方案中,生产者发送数据到broker后,会等待所有isr都同步成功后才会返回成功。这种方式的安全性最好,但是会导致较高的延迟,因此在吞吐量较高的生产环境中慎用。
需要注意的是,acks=-1并不能完全避免消息丢失,当生产者发送消息时,如果有isr节点正在发送网络问题或者故障,可能会导致消息无法复制到所有副本节点,从而导致消息丢失。
问题1: 如果Broker 一直没有给ack响应,如何解决?
设置超时时间,如果超市则触发重试策略,多次重试失败则进行告警
问题2:每发送一次,Broker就要给予一次响应,请问这样是否会对网络带宽产生影响呢? 如果产生, 如何解决呢?
会产生影响。这里引入缓冲池的策略,攒齐一批数据后,异步发送给broker,只需对这一批数据进行相应即可
问题3:通过一批一批的异步发送方式, 如果Broker端对这一批数据没有给予响应,但是缓存池中数据已经满了,如何解决?
选择清空缓存池 / 不清空,如果数据是可重复读的,那么直接让程序报错即可,通知处理。处理后,重新获取发送即可,如果数据是不可重复读,为了避免此种问题,我们可以数据先在某个其他位置保存(备份),当数据生产成功,删除对应的数据,生产不成功,,后续直接从保存的位置中获取生产即可。
Broker端
- 多副本机制:Kafka 通过将数据写入多个副本来提高可用性和可靠性。每个 Topic 的每个分区(Partition)都有多个副本,其中一个副本是 Leader,其他副本是 Follower。Producer 发送消息时,消息首先写入 Leader 副本,Leader 副本再将消息同步到所有 Follower 副本,只有当 Leader 和所有 Follower 副本都确认已经成功写入消息后,Producer 才会认为消息发送成功。在某个副本故障或不可用时,Kafka 会自动将 Leader 副本切换到其他 Follower 副本,以确保数据不会丢失。
- 持久化机制:Kafka Broker 将消息持久化到磁盘中,以确保即使在节点故障或重启后,也能够恢复数据。Kafka Broker 会将消息写入到本地磁盘的日志文件中,并定期将日志文件刷写到磁盘中。这样即使 Broker 发生宕机,可以通过读取磁盘上的日志文件来恢复数据。
消费端
kafka消费端通过消费者组来保证数据不丢失。具体来说,消费者组是一组消费者的集合,他们共同消费一个或多个topic的消息。每个消费者在消费数据时,只能消费其中的一部分分区。同一个分区只能被同一个消费者组中的一个消费者消费,而一个消费者可以消费多个分区。这种机制可以保证同一个消费者组中的消费者不会重复消费,并可以实现负载均衡提高效率。
当消费者从broker拉取数据时,kafka消费端会将消费者的offset保存下来。消费者组中的每个消费者,都会独立的保存自己消费的位置,这样即使其中一个消费者故障,其他消费者仍可以继续消费不丢失数据。
此外,消费者还可以通过设置 auto.commit.interval.ms 参数来定期将消费的位置提交到 Kafka Broker 中。这样即使消费者出现故障或重启,也可以通过从 Kafka Broker 中获取消费位置来恢复数据,避免数据丢失。
同时消费者也可以手动提交消费位置,拉取数据消费完后再提交,这样能保证数据不会丢失,但是可能存在重复消费的问题。
综上所述,Kafka 消费端通过消费者组机制和消费位置的保存来保证数据不丢失。在实际应用中,需要根据实际需求来设置消费者组和消费位置的参数,以达到更高的可靠性和稳定性。
Kafka High WaterMark
Kafka中的High Watermark(高水位)是指一个分区中已经被成功写入的消息的最高偏移量。也就是说,High Watermark表示消费者可以安全地消费的最高消息偏移量。
在Kafka中,High Watermark的位置由Broker维护并更新。每当Broker成功地将消息写入一个分区时,就会更新该分区的High Watermark。消费者在消费消息时,只能消费High Watermark之前的消息。这是因为High Watermark之后的消息可能还没有被完全复制到所有的副本中,消费这些消息可能会导致数据不一致。
当消费者消费完一个分区中的所有消息后,它可以通过查询分区的High Watermark来确定是否有新的消息可供消费。如果High Watermark没有变化,则表示没有新的消息可供消费。如果High Watermark有变化,则表示有新的消息可供消费。
High Watermark在Kafka中扮演着非常重要的角色,它不仅用于保证数据一致性,还可以用于控制消费者的消费速率,从而避免消费者消费速度过快导致的消息丢失问题。
high watermark更新过程
- 生产者将消息发送到 Kafka 集群的各个 broker 上的分区(Partition)中。
- Kafka 的分区副本(Replica)有一个主副本(Leader)和一个或多个追随者副本(Follower)。生产者将消息发送到主副本,然后主副本将消息写入其本地日志(Log)。
- 追随者副本从主副本拉取消息并将其写入其本地日志。追随者副本会向主副本发送一个确认(acknowledgement),表示已成功写入消息。
- 主副本会等待所有 ISR(In-Sync Replicas,同步副本集)中的追随者副本发送确认。一旦主副本收到所有确认,它会认为这个消息已经提交(committed)。
- 主副本会更新其 High Watermark,将其设置为已提交消息的最小偏移量。
- 追随者副本会定期从主副本获取 High Watermark 的更新。追随者副本也会更新其本地的 High Watermark。
- 消费者从 Kafka 集群中消费消息时,只会消费小于 High Watermark 的消息。这样可以确保消费者只消费已提交的消息,从而保证数据的一致性。
如果有一个follwer副本一直未确认成功写入消息,主副本的high watermark会卡住不更新吗?
如果有一个 follower 副本一直未确认成功写入消息,主副本的 High Watermark 是否会卡住不更新,取决于 Kafka 的配置参数 min.insync.replicas
和 acks
。
min.insync.replicas
是一个配置参数,用于指定在认为消息已提交(committed)之前,必须至少有多少个 ISR(同步副本集)中的副本收到消息。例如,如果 min.insync.replicas
设置为 2,那么至少需要有 2 个副本(包括主副本)收到消息,才会认为消息已提交。
acks
是生产者配置的参数,表示生产者需要等待多少个副本确认消息接收。如果设置为 acks=all
或者等于 -1,那么生产者将等待所有 ISR 中的副本确认消息接收
-
如果
min.insync.replicas
的值已经满足,即使有一个 follower 副本未确认,主副本的 High Watermark 仍然会更新,因为已经有足够的副本确认了消息。 -
如果
min.insync.replicas
的值未满足,那么主副本的 High Watermark 将会卡住不更新,因为没有足够的副本确认消息。此外,如果生产者的acks
设置为all
或等于 -1,那么生产者也会阻塞,直到所有 ISR 中的副本都确认消息接收。
在某些情况下,如果有一个 follower 副本一直未确认成功写入消息,主副本的 High Watermark 可能会卡住不更新。这取决于 Kafka 的配置参数 min.insync.replicas
和生产者的 acks
设置。
如果有一个 follower 副本一直未确认成功写入消息,主副本的 High Watermark 卡住不更新那会影响消费者消费,kafka如何解决这个问题?
如果有一个 follower 副本一直未确认成功写入消息,导致主副本的 High Watermark 卡住不更新,确实可能会影响消费者的消费进度。但是 Kafka 有一些机制来解决这个问题:
-
副本移除:Kafka 会定期检查每个副本的延迟情况。如果一个 follower 副本的延迟超过了配置参数
replica.lag.time.max.ms
所指定的时间,那么这个副本将被认为是 “延迟”(lagging),并从 ISR(同步副本集)中移除。一旦该副本从 ISR 中移除,它将不再影响 High Watermark 的更新。当然,这也意味着副本数量减少,可能会降低数据的可靠性,所以需要权衡。 -
副本恢复:Kafka 会尝试恢复延迟的 follower 副本。当延迟的副本追赶上主副本,并且满足一定条件(例如延迟时间低于
replica.lag.time.max.ms
),它将重新加入 ISR。这样一来,High Watermark 可以继续更新,同时保证了数据的可靠性。 -
监控和告警:Kafka 集群的监控和告警系统可以帮助我们及时发现副本延迟的问题。当检测到副本延迟时,可以立即采取措施,例如检查网络问题、磁盘故障等,以尽快解决问题,确保 High Watermark 正常更新。
-
调整参数:可以根据实际情况调整 Kafka 的配置参数,例如
min.insync.replicas
、acks
和replica.lag.time.max.ms
等,以平衡数据的可靠性和消费者的消费进度。
总之,虽然有可能出现 High Watermark 卡住不更新的情况,但 Kafka 提供了一些机制来解决这个问题,以确保消费者可以正常消费。然而,这些机制可能会降低数据的可靠性,因此需要根据实际情况进行权衡。
Kafka如何进行leader选举
kafka使用zookeeper来进行leader选举。当一个分区的leader副本失效或者发生故障时,kafka需要从isr中选择一个新的leader。
-
kafka会在zookeeper中为每个分区创建一个临时节点,用于存储当前的leader副本信息。
-
当一个leader副本失效或者发生故障时,kafka控制器会感知到这个变化。kafka控制器是kafka集群的一个特殊broker,负责管理分区的leader选举和副本状态。
-
kafka控制器会触发一个新的leader选举。首先,他会检查当前分区的同步副本集,从中选择一个新的leader。通常kafka会选择具有最小broker Id的副本作为新的leader。
-
一旦新的leader被选中,kafka控制器会更新zookeeper中分区的临时节点,将新的leader信息写入其中。
-
所有follwer副本会监视zookeeper中分区的临时节点。当临时及诶单发生变化时,follwer副本会感知到新的leader,并开始与新的leader进行同步。
-
同时kafka控制器会发送一个通知给所有关心该分区的消费者和生产者,告知他们新的leader信息。消费者和生产者会根据新的leader信息更新他们的链接,以便继续进行消息的生产和消费。
通过这个过程,Kafka 能够在 leader 副本失效或发生故障时,自动选择一个新的 leader,并确保集群的高可用性。需要注意的是,在 leader 选举期间,分区可能会暂时不可用,直到新的 leader 被选定并与其他副本同步。因此,Kafka 的 leader 选举会在保证数据一致性的同时,尽量减小对生产和消费的影响。