Kafka笔记_1
消费
watermark
水位线以下的数据是消费者可以消费的数据
消费者组中的消费者和分区之间的分配关系
- 同一个消费者组中的消费者都订阅同一个主题,所以消费者组中的多个消费者可以共同消费同一个主题中的所有数据
- 为了避免数据被重复消费,所以主题一个分区的数据只能被组中的一个消费者消费,所以两个消费者不能同时消费一个分区的数据。但是一个消费者可以同时消费多个分区的数据。
消费者分区分配策略(4种)
- 具体的分配策略实际上是由消费者组中的
Leader
决定的,Leader
就是群主,是第一个加入消费者组的消费者 - 消费者加入群组时,发送一个
JoinGroup
,群主负责给每一个消费者分配一个分区
轮询分配策略(RoundRobinAssignor
)
- 每个消费者组中的消费者都含有一个自动生成的
UUID
作为memberid
- 轮询策略会将每个消费者按照
memberid
进行排序,所有member
消费的主题分区根据主题名称进行排序 - 将主题分区轮询分配给对应的订阅用户,未订阅当前轮询主题的消费者会跳过
范围分配策略(RangeAssignor
)
- 每个
Topic
的partition
数计算出每个消费者应该分配的分区数量,分配原则就是一个主题的分区尽可能平分,如果不能平均分配,则按照顺序向前补齐。
- 假设目前有五个分区分给两个消费者,
5 / 2 = 2, 5 % 2 = 1
。则剩下一个分区补在第一个消费者中,则分配结果为[123][45]
- 假设目前有五个分区分配给三个消费者,
5 / 3 = 1, 5 % 3 = 2
,最后分配结果是[12][34][5]
- 范围分配策略针对单个
Topic
的情况下比较均衡,如果多个Topic
,则member
靠前的排序可能比靠后的排序负载多很多,也不够理想
粘性分区(StickyAssignor
)
- 第一次分配后,每个组成员都保留分配给自己的分区信息。如果消费者加入或者退出,则进行分区再分配时(一般是消费者退出45s以后,才会进行再分配,因为又要考虑可能恢复的情况),尽可能保证消费者原有分区不变,重新对加入或者退出消费者的分区进行分配。
优化的粘性分配策略(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组件
- 通信用组件
SocketServer
,NetworkClient
,生产者中的缓冲区,ZooKeeper
等等
LSO、LEO、HW
含义
LSO (Log Start Offset, Log Stable Offset)
- 第一个是数据文件的起始偏移量
- 第二个表示的位移值是用来判断事务型消费者的可见性,就是事务的隔离级别
- 一个是
read_committed
, 另一个是read_uncommitted
,如果没有使用事务,则这个偏移量没有意义
- 一个是
LEO (Log End Offset)
下一个要写入的数据偏移量,是不存在的。水位线靠这个推动增长HW
高水位线的意思,是Kafka
为了数据一致性增加的一种数据隔离方式,消费者只能消费到小于高水位线的数据
Controller
选举如何实现
Kafka
在4.0版本以后,将会完全抛弃ZooKeeper
,现在Controller
选举还是依赖ZooKeeper
实现的,所有的Broker
都会监听ZooKeeper
中的一个Controller
临时节点。如果没有创建,则Broker
会申请创建,创建成功,则该Broker
就是集群的Controller
。一旦失去和ZooKeeper
的通信,临时节点就会消失,就会重新进行选举,并且Controller纪元
就会更新
AR ISR OSR
的含义
AR
是分区的所有副本集合ISR
是正在同步数据的副本列表,列表的第一个就是分区的Leader
副本,其他就是Follower
副本OSR
就是没有处于同步数据的副本列表,一旦副本拉去数据满足了特定的条件。则OSR
会移除并增加到ISR
中。同样如果副本没有拉取数据满足特定的条件,就会从ISR
中移除,放到OSR
中。这些就是ISR
列表的收缩和扩张,权衡数据的可靠性和性能之间的关系
Producer
消息重复或者消息丢失的原因
- 主要就是
Kafka
为了提高数据可靠性提供的重试机制,数据一旦发送失败了,数据就丢失了 - 数据重复,恰恰是因为开启重试机制以后,如果网络阻塞或者不稳定,导致数据需要重新发送,数据就有可能会重复
- 幂等性操作要求必须开启重试功能和
ACKS = -1
,这样可以确保数据不会丢失Kafka
提供幂等性操作只能保证同一个生产者会话中同一个分区中的数据不会重复,一旦数据发送过程中,生产者对象重启,幂等性操作失效,此时需要使用事务功能解决跨会话的幂等性操作,但是跨分区的幂等性操作是无法实现的。
Consumer
消息重复或消息丢失的原因
- 是消费者提交偏移量的问题,消费者为了防止意外情况下,重启后不知道从哪里开始消费,会每5s自动保存偏移量,但是这种自动保存偏移量的操作是基于时间的,一旦未到达时间,消费者重启了,那么消费者可能重复消费数据
Kafka
提供自动保存偏移量的功能的同时,也提供了手动保存偏移量的两种方式,一个同步提交,另一个是异步提交。本质上都是提交一批数据的最后一个偏移的值,但是可能会出现,偏移量已经提交完毕了,但是拉取的数据还没有处理完毕,消费者重启了,此时有些数据就无法消费到,造成了数据丢失
Kafka
数据如何保证有序
- 有序需要考虑生产有序,存储有序和消费有序。
- 生产有序 就是生产者对象需要给数据增加序列号,用于标记数据的顺序,在服务端进行缓存数据的比对,一旦发现数据是乱序的,就需要让生产者客户端进行数据排序,然后重新发送数据,从而保证数据的有序。不过这里缓存的比对,最多只能有5条数据的比对,所以生产者客户端需要配置在途请求缓冲区的请求队列数据设置成5,否则数据依然可能乱序。因为服务端的缓存数据是以分区为单位的,所以需要生产者客户端将数据发送到一个分区中,如果数据发送到多个分区中,无法保证顺序,这就是生产有序的意思
- 存储有序
Kafka
的服务端获取数据以后会将数据顺序写入日志文件,保证了存储有序,也只能保证一个分区的数据有序 - 消费有序
Kafka
在存储数据时会给数据增加一个访问的偏移量值,消费者只能按照偏移量的方式顺序访问,并且一个分区的数据只能被消费者组中的一个消费者消费,那么按照偏移量方式读取的数据就不会出现乱序的情况,从而实现消费有序
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Sangs Blog!