《Apache Kafka 实战》 阅读笔记
2023-6-15|2023-7-4
麦兜
type
Post
status
Published
date
Jun 15, 2023
slug
summary
tags
Kafka
消息引擎
category
学习思考
password
icon
Kafka 的设计
kafka 是支持消息队列和发布订阅模型。
一个 topic 可以有多个分区,分区内部是有序的,如果想保证消息有序设立一个分区即可。分区是分布在不同的 broker (kafka 服务端) ,在 kafka 集群中一个分区存在一个leader 副本和 follower 多个副本,只有 leader 副本才可以接受客户端请求,follower 只做请求转发和获取数据。
Kafka 对于没有提交成功的消息不做任何交付保证,它只保证在 ISR(正常的 follower 副本集合) 存活的情况下”已提交“的消息不会丢失。
Producer 开发
Producer 发送消息流程
producer 使用一个用户线程将待发送的消息封装进一个 ProducerRecord 类实例,然后将其序列化之后发送给 partitioner,确定了目标分区后送到位于 producer 程序中的一块内存缓冲区中而 producer 的另一个工作线程(I/O发送线程)则负责实时地从该缓冲区中提取出准备就绪的消息封装进一个批次(batch),统一发送给对应的 broker。如果发送成功及返回 RecordMetadata ,否者返回错误让 producer 继续重试。
Producer 的相关参数与注意事项
ProducerRecord 的分区和 key 可以不用指定,由 Kafka 自行确定目标分区,发送到 broker 端的任何消息的格式都必须是字节数组,需要配置序列化器。
ProducerRecord 的参数 timestamp 让 Kafka 给出即可,因为索引文件是按照这个参数严格排序。
send
()
的回调方法的两个输入参数 metadata 和 exception 不会同时非空,也就是说至少有一个是 null。当消息发送成功时,exception是 null;反之,若消息发送失败,metadata就是 null。因此在写 producer程序时,最好写if语句进行判断。RecordMetadata 包含了已发送消息的所有元数据信息,包括消息发送的topic、分区以及该消息在对应分区的位移信息。
参数 | 说明 | 注意事项 |
acks | 用于消息的持久性 | 参数有0、1、all(-1),默认使用1。0:性能最高,安全性最低,请求后不处理 broker任何回应,1:broker 的leader 节点写入本地日之后便返回响应。all(-1):安全性最高,性能最差, 整个集群写入本地日志才可以返回。 |
buffer.memory | 消息的缓冲区大小,单位是字节。 | Kafka 由于使用异步发送消息的设计架构, producer 启动时会首先创建一块内存缓冲区用于保存待发送的消息,再让异步 I/O 发送到 broken。所以这个参数会影响到写的吞吐量。 |
retries | 处理瞬时异常消息重发次数 | 默认值是0。重试可能造成消息的重复发送,消息的乱序。max.in.flight.requets.per.connection参数设置为1可以保证一个时刻只能发送一个请求,可以解决乱序问题。 |
retry.backoff.ms | 重发限制时间 | 默认是100毫秒 |
batch.size | 发送批次大小限制 | batch.size 参数默认值是16384,即16KB。producer 并不总是等待 batch 满了才发送消息,会配合 linger.ms 参数控制发送频率。 合理增加此值吞吐量也会也对应的增加。 |
linger.ms | 发送批次间隔时常 | linger.ms 参数就是控制消息发送延时行为的。该参数默认值是0,表示消息需要被立即发送,无须关心 batch 是否已被填满。 |
Consumer 开发
在 kakfa 的 Consumer 有一个概念叫 Consumer Group 用于实现高伸缩性、高容错性的 Consumer 机制,如果 Consumer Group 里面的某个 Consumer 挂掉了,Consumer 负责的分区转交给其他 Consumer 来负责,不会丢失数据这个过程被称为重平衡(Rebalance)。
Consumer Group的 Rebalance 本质上是一组协议,它规定了一个 Consumer Group 是如何达成一致来平均分配订阅 topic的所有分区的。
Rebalance 达到的条件有三个,1、Consumer 变更加入或者离开 2、Consumer Group 订阅的 Topic 有变更 3、Topic 分区有变更。Consumer 变更这个条件不一定是消费者挂掉了,而是无法在指定的时间内完成消息的处理。
rebalance 分区分配默认的分配策略是 Range。用户根据 consumer 参数partition.assignment.strategy 来进行设置,用户也可以实现分配器。Range 策略主要是基于范围的思想。它将单个 Topic 的所有分区按照顺序排列,然后把这些分区划分成固定大小的分区段并依次分配给每个 consumer。
由于 Kafka 目前只提供单个分区内的消息顺序,而不会维护全局的消息顺序,因此如果用户要实现 topic 全局的消息读取顺序,就只能通过让每个 Consumer group 下只包含一个 Consumer 实例的方式来间接实现。
Rebalance 流程
加入组:这一步中组内所有 consumer(即 group.id 相同的所有 consumer 实例)向 coordinator 发送 JoinGroup请求。当收集全 JoinGroup 请求后,coordinator 从中选择一个 consumer 担任 group 的leader,并把所有成员信息以及它们的订阅信息发送给 leader。特别需要注意的是,group 的 leader 和coordinator 不是一个概念。leader 是某个consumer 实例,coordinator 通常是Kafka 集群中的一个 broker。另外 leader 而非 coordinator 负责为整个 group 的所有成员制定分配方案。
同步更新分配方案:这一步中 leader 开始制定分配方案,即根据前面提到的分配策略决定每个 consumer 都负责哪些 topic 的哪些分区。一旦分配完成,leader 会把这个分配方案封装进 SyncGroup 请求并发送给 coordinator。比较有意思的是,组内所有成员都会发送 SyncGroup请求,不过只有 leader发送的 SyncGroup请求中包含了分配方案。coordinator 接收到分配方案后把属于每个 consumer 的方案单独抽取出来作为 SyncGroup 请求的 response 返还给各自的 consumer。