Kafka - 生产者 - 压缩算法

发布时间 2023-08-31 14:35:22作者: frank_cui

总结

1.Producer 端压缩、Broker 端保持、Consumer 端解压缩。

2.开启压缩的最佳实践:

  • Producer 端完成的压缩,那么启用压缩的一个条件就是 Producer 程序运行机器上的 CPU 资源要很充足。
  • 如果你的环境中带宽资源有限,那么我也建议你开启压缩。如果你的机器 CPU 资源有很多富余,强烈建议你开启 zstd 压缩,这样能极大地节省网络资源消耗。

 

kafka数据格式

Kafka 的消息层次都分为两层:消息集合(message set)以及消息(message)。一个消息集合(message set)中包含若干条日志项(record item),而日志项才是真正封装消息的地方。Kafka 底层的消息日志由一系列消息集合日志项组成。Kafka 通常不会直接操作具体的一条条消息,它总是在消息集合这个层面上进行写入操作。

 

目前 Kafka 共有两大类消息格式,社区分别称之为 V1 版本和 V2 版本。V2 版本是 Kafka 0.11.0.0 中正式引入的。V2 版本主要是针对 V1 版本的一些弊端做了修正:

1.把消息的公共部分抽取出来放到外层消息集合里面,这样就不用每条消息都保存这些信息了。我来举个例子。原来在 V1 版本中,每条消息都需要执行 CRC 校验,但有些情况下消息的 CRC 值是会发生变化的。比如在 Broker 端可能会对消息时间戳字段进行更新,那么重新计算之后的 CRC 值也会相应更新;再比如 Broker 端在执行消息格式转换时(主要是为了兼容老版本客户端程序),也会带来 CRC 值的变化。鉴于这些情况,再对每条消息都执行 CRC 校验就有点没必要了,不仅浪费空间还耽误 CPU 时间,因此在 V2 版本中,消息的 CRC 校验工作就被移到了消息集合这一层。

2.V2 版本还有一个和压缩息息相关的改进,就是保存压缩消息的方法发生了变化。之前 V1 版本中保存压缩消息的方法是把多条消息进行压缩然后保存到外层消息的消息体字段中;而 V2 版本的做法是对整个消息集合进行压缩。显然后者应该比前者有更好的压缩效果。我对两个版本分别做了一个简单的测试,结果显示,在相同条件下,不论是否启用压缩,V2 版本都比 V1 版本节省磁盘空间。当启用压缩时,这种节省空间的效果更加明显,就像下面这两张图展示的那样:

 

何时压缩?

在 Kafka 中,压缩可能发生在两个地方:生产者端和 Broker 端。

压缩一般发生在生产者端

生产者程序中配置 compression.type 参数即表示启用指定类型的压缩算法。比如下面这段程序代码展示了如何构建一个开启 GZIP 的 Producer 对象:

这里比较关键的代码行是 props.put(“compression.type”, “gzip”),它表明该 Producer 的压缩算法使用的是 GZIP。这样 Producer 启动后生产的每个消息集合都是经 GZIP 压缩过的,故而能很好地节省网络传输带宽以及 Kafka Broker 端的磁盘占用。

 Properties props = new Properties();
 props.put("bootstrap.servers", "localhost:9092");
 props.put("acks", "all");
 props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
 props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
 // 开启GZIP压缩
 props.put("compression.type", "gzip");
 
 Producer<String, String> producer = new KafkaProducer<>(props);

 

压缩何时会发生在broker端?

情况一:Broker 端指定了和 Producer 端不同的压缩算法

Producer 说:“我要使用 GZIP 进行压缩。”Broker 说:“不好意思,我这边接收的消息必须使用 Snappy 算法进行压缩。”你看,这种情况下 Broker 接收到 GZIP 压缩消息后,只能解压缩然后使用 Snappy 重新压缩一遍。

 

Broker 端也有一个参数叫 compression.type,和上面那个例子中的同名。但是这个参数的默认值是 producer,这表示 Broker 端会“尊重”Producer 端使用的压缩算法。可一旦你在 Broker 端设置了不同的 compression.type 值,就一定要小心了,因为可能会发生预料之外的压缩 / 解压缩操作,通常表现为 Broker 端 CPU 使用率飙升。

情况二:Broker 端发生了消息格式转换

为了兼容老版本的消费者程序。还记得之前说过的 V1、V2 版本吧?在一个生产环境中,Kafka 集群中同时保存多种版本的消息格式非常常见。为了兼容老版本的格式,Broker 端会对新版本消息执行向老版本格式的转换。这个过程中会涉及消息的解压缩和重新压缩。一般情况下这种消息格式转换对性能是有很大影响的。

 

除了这里的压缩之外,它还让 Kafka 丧失了引以为豪的 Zero Copy 特性。

 

何时解压缩?

最佳实践 —— Producer 端压缩、Broker 端保持、Consumer 端解压缩。

 

各种压缩算法对比

看一个压缩算法的优劣,有两个重要的指标:

一个指标是压缩比,原先占 100 份空间的东西经压缩之后变成了占 20 份空间,那么压缩比就是 5,显然压缩比越高越好;

另一个指标就是压缩 / 解压缩吞吐量,比如每秒能压缩或解压缩多少 MB 的数据。同样地,吞吐量也是越高越好。

 

对于 Kafka 而言,它们的性能测试结果出奇得一致,即:

  • 吞吐量方面:LZ4 > Snappy > zstd 和 GZIP
  • 压缩比方面,zstd > LZ4 > GZIP > Snappy

 

开启压缩的最佳实践

开启压缩的最佳实践:

  • Producer 端完成的压缩,那么启用压缩的一个条件就是 Producer 程序运行机器上的 CPU 资源要很充足。
  • 如果你的环境中带宽资源有限,那么我也建议你开启压缩。如果你的机器 CPU 资源有很多富余,强烈建议你开启 zstd 压缩,这样能极大地节省网络资源消耗。