人生第一份工作■Kafka架构原理,也就这么回事( 四 )


相对的 , 将服务器 ACK 级别设置为 0 , 可以保证生产者每条消息只会被发送一次 , 即 At Most Once 语义 。
At Least Once 可以保证数据不丢失 , 但是不能保证数据不重复;相对的 , At Most Once 可以保证数据不重复 , 但是不能保证数据不丢失 。
但是 , 对于一些非常重要的信息 , 比如交易数据 , 下游数据消费者要求数据既不重复也不丢失 , 即 Exactly Once 语义 。
0.11 版本的 Kafka , 引入了幂等性:Producer 不论向 Server 发送多少重复数据 , Server 端都只会持久化一条 。
即:
At Least Once + 幂等性 = Exactly Once 要启用幂等性 , 只需要将 Producer 的参数中 enable.idompotence 设置为 true 即可 。
开启幂等性的 Producer 在初始化时会被分配一个 PID , 发往同一 Partition 的消息会附带 Sequence Number 。
而 Borker 端会对
但是 PID 重启后就会变化 , 同时不同的 Partition 也具有不同主键 , 所以幂等性无法保证跨分区会话的 Exactly Once 。
消费者
消费方式
Consumer 采用 Pull(拉取)模式从 Broker 中读取数据 。
Consumer 采用 Push(推送)模式 , Broker 给 Consumer 推送消息的速率是由 Broker 决定的 , 很难适应消费速率不同的消费者 。
它的目标是尽可能以最快速度传递消息 , 但是这样很容易造成 Consumer 来不及处理消息 , 典型的表现就是拒绝服务以及网络拥塞 。
而 Pull 模式则可以根据 Consumer 的消费能力以适当的速率消费消息 。 Pull 模式不足之处是 , 如果 Kafka 没有数据 , 消费者可能会陷入循环中 , 一直返回空数据 。
因为消费者从 Broker 主动拉取数据 , 需要维护一个长轮询 , 针对这一点 ,Kafka 的消费者在消费数据时会传入一个时长参数 timeout 。
如果当前没有数据可供消费 , Consumer 会等待一段时间之后再返回 , 这段时长即为 timeout 。
分区分配策略
一个 Consumer Group 中有多个 Consumer , 一个 Topic 有多个 Partition , 所以必然会涉及到 Partition 的分配问题 , 即确定哪个 Partition 由哪个 Consumer 来消费 。
Kafka 有两种分配策略 , 一个是 RoundRobin , 一个是 Range , 默认为Range , 当消费者组内消费者发生变化时 , 会触发分区分配策略(方法重新分配) 。
①RoundRobin
人生第一份工作■Kafka架构原理,也就这么回事
本文插图
RoundRobin 轮询方式将分区所有作为一个整体进行 Hash 排序 , 消费者组内分配分区个数最大差别为 1 , 是按照组来分的 , 可以解决多个消费者消费数据不均衡的问题 。
但是 , 当消费者组内订阅不同主题时 , 可能造成消费混乱 , 如下图所示 , Consumer0 订阅主题 A , Consumer1 订阅主题 B 。
人生第一份工作■Kafka架构原理,也就这么回事
本文插图
将 A、B 主题的分区排序后分配给消费者组 , TopicB 分区中的数据可能分配到 Consumer0 中 。
②Range
人生第一份工作■Kafka架构原理,也就这么回事
本文插图
Range 方式是按照主题来分的 , 不会产生轮询方式的消费混乱问题 。
但是 , 如下图所示 , Consumer0、Consumer1 同时订阅了主题 A 和 B , 可能造成消息分配不对等问题 , 当消费者组内订阅的主题越多 , 分区分配可能越不均衡 。
人生第一份工作■Kafka架构原理,也就这么回事
本文插图
Offset 的维护
由于 Consumer 在消费过程中可能会出现断电宕机等故障 , Consumer 恢复后 , 需要从故障前的位置继续消费 。


推荐阅读