kafka 生产者压缩算法

  • 为什么要压缩
  • 如何压缩
  • 何时压缩
  • 何时解压缩
  • 各种压缩算法对比


为什么要压缩

  压缩是一种时间换空间的动作。具体来说就是用CPU时间去换取磁盘空间或网络I/O传输量,希望以较小的CPU开销带来更少的磁盘占用或者更少的网络I/O传输。

如何压缩

  要搞清楚kafka如何压缩消息。就要从kafka的消息格式说起。目前kafka的有两大类消息格式:V1版本和V2版本。
  无论是那个版本,kafka的消息层次都是两层:消息集合以及消息。一个消息集合中包含若干条日志项,而日志项才是真正封装消息的地方。kafka底层的消息日志由一系列消息集合日志项组成。kafka通常不会直接操作具体的一条条消息,他总是在消息集合这个层面上进行写入操作。
  V2相对V1有一些改进。
1:把消息的公共部分抽取出来放到外层消息集合里面,这样就不用每条消息都保存这些信息了。
2:保存压缩消息的方法发生了改变。在v1版本中,是把多条消息进行压缩然后保存到外层消息的消息字段中;而V2版本的做法是对整个消息集合进行压缩。显然后者应该比前者有更好的压缩效果。

何时压缩

  在kafka中压缩可能发生在两个地方:生产者端和broker端。
  生产者程序中配置compression.type参数即表示开启指定类型的压缩算法。如:

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 端接收到消息后仅仅是原封不动地保存而不会对其进行任何修改。
  但是有两种特殊情况:
1:Broker 端指定了和 Producer 端不同的压缩算法。
2:Broker 端发生了消息格式转换。
  第一种使用不同的压缩算法很好理解。主要是第二种:
  所谓的消息格式转换主要是为了兼容老版本的消费者程序。为了兼容老版本的格式,Broker 端会对新版本消息执行向老版本格式的转换。这个过程中会涉及消息的解压缩和重新压缩。一般情况下这种消息格式转换对性能是有很大影响的,除了这里的压缩之外,它还让 Kafka 丧失了引以为豪的 Zero Copy 特性。

何时解压缩

  既然有压缩就必然有解压缩,我们容易想到的肯定是在Consumer端要进行解压缩。还有另一种就是会在borker端进行解压缩。
  Consumer会自动进行解压缩的。此时就有一个问题:Consumer如何知道使用那种算法进行解压缩?其实:Kafka 会将启用了哪种压缩算法封装进消息集合中,这样当 Consumer 读取到消息集合时,它自然就知道了这些消息使用的是哪种压缩算法。
  borker端进行的解压缩,我们要注意此处的解压缩和上面的消息格式转换时的解压缩不是一个。此处的解压缩是用于在保存消息之前对消息进行各种验证

总结:Producer 端压缩、Broker 端保持、Consumer 端解压缩。

各种压缩算法对比

压缩算法有:GZIP、Snappy 、 LZ4和Zstandard 算法(简写为 zstd)
看一个压缩算法的优劣,有两个重要的指标:
1:一个指标是压缩比
2:另一个指标就是压缩 / 解压缩吞吐量,比如每秒能压缩或解压缩多少 MB 的数据
在吞吐量方面:LZ4 > Snappy > zstd 和 GZIP;
在压缩比方面:zstd > LZ4 > GZIP > Snappy