1.1 分区
分区的作用就是提供负载均衡的能力
1.2 分区策略
分区策略是决定生产者将消息发送到哪个分区的算法
- 显式地配置生产者端的参数partitioner.class
- 实现org.apache.kafka.clients.producer.Partitioner接口
- int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster);
1.2.1 轮询策略(Round-robin)
轮询策略有非常优秀的负载均衡表现,它总是能保证消息最大限度地被平均分配到所有分区上,故默认情况下它是最合理的分区策略,也是我们最常用的分区策略之一。
1.2.2 随机策略(Randomness)
如果追求数据的均匀分布,还是使用轮询策略比较好。 事实上,随机策略是老版本生产者使用的分区策略,在新版本中已经改为轮询了。
1.2.3 按消息键保序策略
Kafka 允许为每条消息定义消息键,简称为 Key。
一旦消息被定义了 Key,那么你就可以保证同一个 Key 的所有消息都进入到相同的分区里面,由于每个分区下的消息处理都是有顺序的,故这个策略被称为按消息键保序策略。
Kafka 默认分区策略实际上同时实现了两种策略:如果指定了 Key,那么默认实现按消息键保序策略;如果没有指定 Key,则使用轮询策略。
1.2.4 其他分区策略
还有一种比较常见的,即所谓的基于地理位置的分区策略。当然这种策略一般只针对那些大规模的 Kafka 集群,特别是跨城市、跨国家甚至是跨大洲的集群。
1.3 压缩算法
Kafka 的消息层次都分为两层:消息集合(message set) 以及 消息(message)。一个消息集合中包含若干条日志项(record item),而日志项才是真正封装消息的地方。
Producer 端压缩、Broker 端保持、Consumer 端解压缩。
2.1.3.1 V1版本和V2版本的区别
- 消息的公共部分抽取出来放到外层消息集合里面,这样就不用每条消息都保存这些信息了
- 在 V2 版本中,消息的 CRC 校验工作就被移到了消息集合这一层。
- V1是对每条消息进行压缩,V2 是对整个消息集合进行压缩
1.3.2 何时压缩
压缩可能发生在两个地方:生产者端和 Broker 端。
生产者程序中配置 compression.type 参数即表示启用指定类型的压缩算法
Borker 压缩的情况:
- Broker 端指定了和 Producer 端不同的压缩算法
- Broker 指定压缩算法且与 Producer 不一致(不指定默认使用 Producer 的压缩算法)
- broker 先解压后使用自己的压缩算法进行压缩
- Broker 端发生了消息格式转换
- 消息格式转换主要是为了兼容老版本的消费者程序(V1 和 V2 的转换)
- 这种消息格式转换对性能是有很大影响的,除了这里的压缩之外,它还让 Kafka 丧失了引以为豪的 Zero Copy 特性。
1.3.3 何时解压
- 通常来说解压缩发生在消费者程序中,,当消息到达 Consumer 端后,由 Consumer 自行解压缩还原成之前的消息。
- Kafka 会将启用了哪种压缩算法封装进消息集合中,这样消费者就能读取到压缩算法去进行解压
- Broker 端写入时都要发生解压缩操作,目的就是为了对消息执行各种验证。
1.3.4 压缩算法对比
- 吞吐量方面:LZ4 > Snappy > zstd 和 GZIP;
- 压缩比方面,zstd > LZ4 > GZIP > Snappy
- 具体到物理资源,使用 Snappy 算法占用的网络带宽最多,zstd 最少
- 在 CPU 使用率方面,各个算法表现得差不多,只是在压缩时 Snappy 算法使用的 CPU 较多一些,而在解压缩时 GZIP 算法则可能使用更多的 CPU
1.3.5 最佳实践
- 启用压缩的一个条件就是 Producer 程序运行机器上的 CPU 资源要很充足
- 带宽资源有限,建议开启压缩
- CPU 资源有很多富余,强烈建议你开启 zstd 压缩