消费

  • watermark水位线以下的数据是消费者可以消费的数据

消费者组中的消费者和分区之间的分配关系

  1. 同一个消费者组中的消费者都订阅同一个主题,所以消费者组中的多个消费者可以共同消费同一个主题中的所有数据
  2. 为了避免数据被重复消费,所以主题一个分区的数据只能被组中的一个消费者消费,所以两个消费者不能同时消费一个分区的数据。但是一个消费者可以同时消费多个分区的数据。

消费者分区分配策略(4种)

  • 具体的分配策略实际上是由消费者组中的Leader决定的,Leader就是群主,是第一个加入消费者组的消费者
  • 消费者加入群组时,发送一个JoinGroup,群主负责给每一个消费者分配一个分区

轮询分配策略(RoundRobinAssignor)

  • 每个消费者组中的消费者都含有一个自动生成的UUID作为memberid
  • 轮询策略会将每个消费者按照memberid进行排序,所有member消费的主题分区根据主题名称进行排序
  • 将主题分区轮询分配给对应的订阅用户,未订阅当前轮询主题的消费者会跳过
    RRA1
    RRA2
    RRA3
    RRA4

范围分配策略(RangeAssignor)

  • 每个Topicpartition数计算出每个消费者应该分配的分区数量,分配原则就是一个主题的分区尽可能平分,如果不能平均分配,则按照顺序向前补齐。
  • 假设目前有五个分区分给两个消费者,5 / 2 = 2, 5 % 2 = 1。则剩下一个分区补在第一个消费者中,则分配结果为[123][45]
  • 假设目前有五个分区分配给三个消费者,5 / 3 = 1, 5 % 3 = 2,最后分配结果是[12][34][5]
  • 范围分配策略针对单个Topic的情况下比较均衡,如果多个Topic,则member靠前的排序可能比靠后的排序负载多很多,也不够理想

RA1

粘性分区(StickyAssignor)

  • 第一次分配后,每个组成员都保留分配给自己的分区信息。如果消费者加入或者退出,则进行分区再分配时(一般是消费者退出45s以后,才会进行再分配,因为又要考虑可能恢复的情况),尽可能保证消费者原有分区不变,重新对加入或者退出消费者的分区进行分配。
    SA1
    SA2

优化的粘性分配策略(CooperativeStickyAssignor)

  • 前三种分配策略在进行重分配的时候使用的是EAGER协议,让当前的所有消费者放弃当前分区,关闭连接,资源清理,重新加入组和等待分配策略,效率较低
  • 从2.4版本开始,粘性分配策略的基础上,优化了重分配的过程,使用的是COOPERATIVE协议。粘性分区分配策略分配的会更加均匀和高效一些
  • COOPERATIVE协议将一次全局重平衡,改成每个小规模的重平衡,直到最终收敛平衡的过程
  • Kafka消费者默认的分区分配就是RangeAssignor(第一次分区分配),CooperativeStickyAssinor(后续的分区分配)

集群的脑裂问题

  • 首先ZooKeeper具有三个Broker,其中有一个Controller,由Broker1创建的
  • 但是此时网络不稳定,Broker1掉线了。ZooKeeper中的Controller临时节点被删除了,同时选举了Broker3作为新的Controller,创建了新的临时节点
  • 此时Broker1恢复了链接,由于是Broker3创建了Controller。所以Broker3才是真正的管理者
  • 但是Broker1此时仍然认为自己是管理者,两个Broker都会向Broker2同步消息,Broker2不知道应该同步谁的消息,这就是脑裂问题

解决

  • ZooKeeper引入了epoch纪元,有一个controller_epoch(不是临时节点),记录的是当前的controller是出现的第几个controller。这样Broker2就可以判断出最新的管理者是谁,从而完成同步消息

总结

Kafka组件

  • 通信用组件 SocketServerNetworkClient,生产者中的缓冲区, ZooKeeper等等

LSO、LEO、HW含义

  1. LSO (Log Start Offset, Log Stable Offset)
    • 第一个是数据文件的起始偏移量
    • 第二个表示的位移值是用来判断事务型消费者的可见性,就是事务的隔离级别
      • 一个是read_committed, 另一个是read_uncommitted,如果没有使用事务,则这个偏移量没有意义
  2. LEO (Log End Offset) 下一个要写入的数据偏移量,是不存在的。水位线靠这个推动增长
  3. HW 高水位线的意思,是Kafka为了数据一致性增加的一种数据隔离方式,消费者只能消费到小于高水位线的数据

Controller选举如何实现

  • Kafka在4.0版本以后,将会完全抛弃ZooKeeper,现在Controller选举还是依赖ZooKeeper实现的,所有的Broker都会监听ZooKeeper中的一个Controller临时节点。如果没有创建,则Broker会申请创建,创建成功,则该Broker就是集群的Controller。一旦失去和ZooKeeper的通信,临时节点就会消失,就会重新进行选举,并且Controller纪元就会更新

AR ISR OSR的含义

  1. AR 是分区的所有副本集合
  2. ISR 是正在同步数据的副本列表,列表的第一个就是分区的Leader副本,其他就是Follower副本
  3. OSR 就是没有处于同步数据的副本列表,一旦副本拉去数据满足了特定的条件。则OSR会移除并增加到ISR中。同样如果副本没有拉取数据满足特定的条件,就会从ISR中移除,放到OSR中。这些就是ISR列表的收缩和扩张,权衡数据的可靠性和性能之间的关系

Producer消息重复或者消息丢失的原因

  • 主要就是Kafka为了提高数据可靠性提供的重试机制,数据一旦发送失败了,数据就丢失了
  • 数据重复,恰恰是因为开启重试机制以后,如果网络阻塞或者不稳定,导致数据需要重新发送,数据就有可能会重复
  • 幂等性操作要求必须开启重试功能和ACKS = -1,这样可以确保数据不会丢失
    • Kafka提供幂等性操作只能保证同一个生产者会话中同一个分区中的数据不会重复,一旦数据发送过程中,生产者对象重启,幂等性操作失效,此时需要使用事务功能解决跨会话的幂等性操作,但是跨分区的幂等性操作是无法实现的。

Consumer消息重复或消息丢失的原因

  • 是消费者提交偏移量的问题,消费者为了防止意外情况下,重启后不知道从哪里开始消费,会每5s自动保存偏移量,但是这种自动保存偏移量的操作是基于时间的,一旦未到达时间,消费者重启了,那么消费者可能重复消费数据
  • Kafka提供自动保存偏移量的功能的同时,也提供了手动保存偏移量的两种方式,一个同步提交,另一个是异步提交。本质上都是提交一批数据的最后一个偏移的值,但是可能会出现,偏移量已经提交完毕了,但是拉取的数据还没有处理完毕,消费者重启了,此时有些数据就无法消费到,造成了数据丢失

Kafka数据如何保证有序

  • 有序需要考虑生产有序,存储有序和消费有序
  • 生产有序 就是生产者对象需要给数据增加序列号,用于标记数据的顺序,在服务端进行缓存数据的比对,一旦发现数据是乱序的,就需要让生产者客户端进行数据排序,然后重新发送数据,从而保证数据的有序。不过这里缓存的比对,最多只能有5条数据的比对,所以生产者客户端需要配置在途请求缓冲区的请求队列数据设置成5,否则数据依然可能乱序。因为服务端的缓存数据是以分区为单位的,所以需要生产者客户端将数据发送到一个分区中,如果数据发送到多个分区中,无法保证顺序,这就是生产有序的意思
  • 存储有序 Kafka的服务端获取数据以后会将数据顺序写入日志文件,保证了存储有序,也只能保证一个分区的数据有序
  • 消费有序 Kafka在存储数据时会给数据增加一个访问的偏移量值,消费者只能按照偏移量的方式顺序访问,并且一个分区的数据只能被消费者组中的一个消费者消费,那么按照偏移量方式读取的数据就不会出现乱序的情况,从而实现消费有序