生产者消息分区
Kafka 的消息组织方式实际上是三级结构:主题 - 分区 - 消息,每个消息只会在一个分区中出现。
分区的作用就是提供负载均衡的能力,不同的分区能够被放置到不同节点的机器上,而数据的读写操作也都是针对分区这个粒度而进行的,这样每个节点的机器都能独立地执行各自分区的读写请求处理。并且,我们还可以通过添加新的节点机器来增加整体系统的吞吐量。
分区策略
轮询策略
这是最常用的策略
随机策略
先计算出该主题总的分区数,然后随机地返回一个小于它的正整数。
按消息键保序策略
Kafka 允许为每条消息定义消息键,一旦消息被定义了 Key,那么你就可以保证同一个 Key 的所有消息都进入到相同的分区里面
消息重试发送时不会重新计算分区,会沿用之前的分区选定
分区实现
首先判断是否消息指定了分区,如果指定了分区则直接使用指定的分区进行发送;如果没有指定,则查看是否指定了分区器,如果没有则使用默认分区策略:查看是否指定了key,如果有key则使用key保序策略;如果没有指定key则使用轮询策略
压缩策略
消息层次:
V1:多个消息组成消息集合,多个消息封装成日志项组成一个消息集合。
V2:消息集合将消息的公共部分抽取出来放到消息集合中。
何时压缩
生产者:生产者配置compression.type参数
Broker:
1.Broker 端指定了和 Producer 端不同的压缩算法,也是compression.type这个参数
2.Broker发生了消息格式转换,例如从V1到V2。
这种显示解压缩后压缩的方式会导致Kafka无法实现零拷贝的机制,因为Kafka的零拷贝是在消费消息的阶段从内核缓存到socket缓存的时机实现的
何时解压缩
Broker:Broker一定会解压缩进行数据校验
Consumer:消费消息前解压缩
压缩算法比较
Kafka支持GZIP、Snappy 和 LZ4,zstd四种压缩算法、
看一个压缩算法的优劣,有两个重要的指标:一个指标是压缩比(压缩前大小/压缩后大小),另一个是吞吐量,即每秒能够压缩、解压缩多少MB。
在吞吐量方面:LZ4 > Snappy > zstd 和 GZIP
在压缩比方面:zstd > LZ4 > GZIP > Snappy
所以最好建议使用zstd
无消息丢失的实现
Kafka 只对“已提交”的消息(committed message)做有限度的持久化保证。
当 Kafka 的若干个 Broker 成功地接收到一条消息并写入到日志文件后,它们会告诉生产者程序这条消息已成功提交。此时,这条消息在 Kafka 看来就正式变为“已提交”消息了
实践
1.producer使用send(msg,callback)不要使用send(msg),后者不会管消息是否提交。
2.producer设置acks = all,表明所有ISR中的副本 Broker 都要接收到消息
3.producer设置retries 为一个较大的值,使producer可以重试发送
4.broker设置unclean.leader.election.enable = false,防止延迟高的副本当选leader
5.consumer设置enable.auto.commit = false,防止consumer自动提交但是消息并未消费