压缩是一种用时间换空间的trade-off(权衡)思想。Kafka中也是运用这种思想,用较小的CPU开销换取更少的磁盘占用或者更少的网络传输。
那么在Kafka中,压缩的是什么呢?就是消息了,为了更好明白Kafka对压缩的改进,首先我们先看看消息的版本。
消息的版本
Kafka有两大消息版本,分别为V1版本和V2版本。不管哪个版本的消息,消息层次都为两层:消息集合和消息。一个消息集合中包含若干条日志项(record item),而日志项才是真正封装消息的地方。那V2版本和V1版本比,有哪些优势呢?
- 消息的公共备份提取到外层的消息集合。比如CRC校验,在V1版本每一个消息都要进行CRC校验,在V2版本,就只需要对外层的消息集合做一个统一的校验。
- V2版本的消息比V1版本的消息更加省空间。
压缩发生的时机
在Kafka中,压缩可能发生在两个地方:生产者端和Broker端。生产者端需要配置compression.type来表示启动指定类型的压缩算法。比如在springboot中为
spring.kafka.producer.compression-type=gzip
生产者进行压缩,大家都比较好理解,节省网络传输的开销嘛,那Broker端为什么也要进行压缩?
其实大多数情况下Broker从Producer端接收到消息后仅仅是原封不动地保存而不会对其进行任何修改。除非一下两种情况:
- Broker和producer端指定了不一样的压缩算法。比如Producer端要gzip压缩,Broker要Snappy压缩,两个人不在一个频道上,这种时候,Broker会选择先解压,再压缩成自己需要的格式。
Broker的端的参数也叫compressison.type。如果发生这种情况,Broker端的CPU使用率会飙升。
- Broker端发生了消息格式转换。
消息格式转换主要是为了兼容老版本的消费者程序。这种消息格式转换对性能影响很大。会让Kafk丧失引以为豪的Zero Copy特性。Broker端的消息从磁盘到网络传输,如果能避免昂贵的内核态数据拷贝,那就可以大大加快数据的传输。
解压缩
解压缩发生在消费者程序,Kafka会把压缩的算法封装进消息集合中,这样消息者拿到消息后,就知道应该使用什么算法来进行解压缩了。
以上总结起来就,Producer 端压缩、Broker 端保持、Consumer 端解压缩。
压缩算法对比
在 Kafka 2.1.0 版本之前,Kafka 支持 3 种压缩算法:GZIP、Snappy 和 LZ4。从 2.1.0 开始,Kafka 正式支持 Zstandard 算法(简写为 zstd)。
看一个压缩算法的优劣,有两个重要的指标:一个指标是压缩比,一个是吞吐量。
上图的Ratio就是压缩比。Compression和Decompress是吞吐量。
最佳实践
什么时候启用压缩会比较好呢?如果Producer端所在机器的CPU资源很充足,那么开启压缩,可以提高传输性能。还有种条件是如果本身带宽有限,那么开压缩比也是个不错的选择。