第4章 Kafka工作机制详解

本文详细介绍了Kafka的消息传递语义,包括at most once、at least once和exactly once,强调了生产者和消费者的ack机制。此外,探讨了Kafka的恢复与备份机制、与zookeeper的交互、metrics、HW、LEO、LSO、ISR和AR的概念及其作用,以及ISR的伸缩机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

4.1 消息传递三种语义

4.1.1 消费者

  • at most once: 消费者fetch消息,然后保存offset,然后处理消息。当消费者保存offset之后,但是在消息处理过程中出现了异常,导致部分消息未能继续处理。那么此后“未处理”的消息将不能被重新fetch到,所以存在丢失数据的情况。想实现“至多一次”的做法是:设置消费者自动提交偏移量,并且设置较小的时间间隔。
  • at least once: 消费者fetch消息,然后处理消息,然后保存offset。如果消息处理成功之后,在保存offset阶段,发生异常导致保存操作未能执行成功,这就导致接下来再次fetch时可能获得上次已经处理过的消息。想实现“至少一次”的做法是:设置消费者自动提交偏移量,但设置很长的时间间隔(或者关闭自动提交偏移量),在处理完消息后,手动调用同步模式提交偏移量consumer.commitSync
  • exactly once,需要将消费者的消费进度和处理结果保存在同一介质中,再将这两个操作封装进一个原子性操作。

为了保证消息不丢失,通常情况下,选用at least once。

4.1.2 生产者

kafka的ack机制

  • 0:producer不等待broker的ack,broker一接收到还没有写入磁盘就已经返回,当broker故障时有可能丢失数据;
  • 1:producer等待broker的ack,partition的leader落盘成功后返回ack,如果在follower同步成功之前leader故障,那么将会丢失数据;
  • -1:producer等待broker的ack,partition的leader和follower全部落盘成功后才返回ack,数据一般不会丢失,延迟时间长但是可靠性高。

4.1.3 Broker配置

Broker有三个可以影响到Kafka的消息可靠性存储的设置。

  1. 默认复制因子default.replication.factor,设置更高的复制因子意味着更多的空间换可靠性,会牺牲更多的磁盘空间,还会导致在集群活跃节点少于因子数量的时候不能提供服务,不建议进行设置,而建议创建topic时根据数据重要程度指定副本数量。
  2. 最少同步副本数:min.insync.replicas,默认是1,若保证数据更高可靠性,建议设置为2,在副本数大于等于2个的时候,能避免数据处于只有一个节点活跃的状态,而必须等待有另外一个broker恢复可用时才可以继续进行数据传输。
  3. Unclean leader选举,建议将unclean.leader.election.enable属性为false,避免非同步副本变为leader,导致数据丢失和不一致。非同步副本中的消息远远落后于leader,如果选举这种副本作为leader可能会造成数据丢失,但会保证服务继续可用。

4.2 Kafka恢复与备份机制

kafka把每个parition的消息复制到多个broker上,任何一个parition都有一个leader和多个follower,备份个数可以在创建topic的时候指定。leader负责处理所有read/write请求,follower像consumer一样从leader接收消息并把消息存储在log文件中。leader还负责跟踪所有的follower状态,如果follower “落后”太多或失效,leader将会把它从replicas同步列表中删除。当所有的follower都将一条消息保存成功,此消息才被认为是“committed”。

4.3 Kafka与zookeeper的交互机制

当一个kafka broker启动后,会向zookeeper注册自己的节点信息,当broker和zookeeper断开链接时,zookeeper也会删除该节点的信息。除了自身的信息,broker也会向zookeeper注册自己持有的topic和partitions信息。

当一个consumer被创建时,会向zookeeper注册自己的信息,此作用主要是为了“负载均衡”。一个group中的多个consumer可以交错的消费一个topic的所有partitions。简而言之,保证此topic的所有partitions都能被此group所消费,为了性能的考虑,让partition相对均衡的分撒到每个consumer上。每一个consumer都有一个唯一的ID(host:uuid,可以通过配置文件指定,也可以由系统生成),此ID用来标记消费者信息,主要是topic+partition信息。

Producer端使用zookeeper用来“发现”broker列表,以及和Topic下每个partition leader建立socket连接并发送消息。

zookeeper上还存放partition被哪个consumer所消费的信息,以及每个consumer目前所消费的partition中的最大offset(0.9.0.0版本之前)。

在kafka 0.9版本之后,kafka为了减少与zookeeper的交互,减少网络数据传输,自己实现了在kafka server上存储consumer消费的topic,partitions,offset信息。

4.4 Kafka metircs

对kafka的metrics主要是对lags的分析,lags是topic/partition的logSize与consumer消费到的offset之间的差值,即producer产生数据的量与consumer消费数据的量的差值,差值越来越大,说明消费数据的速度小于产生数据的速度。一般可以认定是consumer出了问题。当然也不能只看某一lags大小,更重要的是关注lags的变化的趋势,当趋势越来越大时,可推断consumer的performance越来越差。

在kafka 0.8.1版本之后,可以通过配置把topic/partition的logsize,offset等信息存储在zookeeper上或存储在kafka server上。在做metrics时,注意可能需要分别从两边获取数据。

获取zookeeper上的kafka数据比较简单,可以通过SimpleConsumer配合zookeeper.getChildren方法获取consumerGroup, topic, paritions信息,然后通过SimpleConsumer的getOffsetsBefore方法获取logSize,fetchOffsets获取topic parition的currentOffsets。

获取kafka server上的数据比较麻烦,目前kafka 0.10提供的kafkaConsumer类主要还是关注topic消费,对consumerGroup及Group和topic关系的获取,还没有提供API。不过可以通过kafka-consumer-groups.sh得到group,topic等信息,这个shell文件里面调用了kafka.admin.ConsumerGroupCommand类,这个类确实提供了一个listGroup方法,可惜这个方法的返回值是void,shell文件的输出是打印到控制台的,并没有返回值。再去研究ConsumerGroupCommand是怎么拿到group的,发现它通过AdminClient对象的listAllConsumerGroup获取的group list,所以只要new出来一个AdminClient就能解决问题。

private static AdminClient getAdminClient(){
   
        if(null != adminClient){
   
            return adminClient;
        }else{
   
            Time time = new SystemTime(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值