生产者压缩算法面面观
- 1、怎么压缩?
- 2、何时压缩?
- 2.1、生产者端
- 2.2、Broker 端
- 3、何时解压缩?
- 4、各种压缩算法对比
压缩的思想,实际就是用时间去换空间的经典 trade-off 思想,在 Kafka 中,就是用 CPU 时间去换磁盘空间或网络 I/O 传输量,希望以较小的 CPU 开销带来更少的磁盘占用或更少的网络 I/O 传输。
1、怎么压缩?
Kafka 的消息层次分为两层:消息集合(message set)以及消息(message)。一个消息集合中包含多条日志项(record item),而日志项才是真正封装消息的地方。Kafka 底层的消息日志由一系列消息集合日志项组成。
Kafka 的设计哲学是关注于消息集合这个层面,而不是直接操作单条消息。也就是说,生产者和消费者通常不会直接与单一的消息进行交互,而是以消息集合为单位进行写入和读取操作。例如,当生产者发送一批消息时,它们会被批量存储在相应的消息集合中;同样地,当消费者消费一批消息时,它也是一次从对应的消息集合中读取多条日志项。这种方式提高了数据处理的效率和并发性能。(linger.ms生产端可以通过这个参数来控制多长时间为一批次,默认是 0,即不等待)
CRC 校验工作:在消息集合这一层。无需对每条消息都做 CRC
压缩工作:对整个消息集合进行压缩。
2、何时压缩?
在 Kafka 中,压缩可能发生在两个地方:生产者端和 Broker 端。
2.1、生产者端
生产者程序中配置 compression.type 参数即表示启用指定类型的压缩算法。这样 Producer 启动后生产的每个消息集合都是经过指定压缩算法压缩过的,故而能很好地节省网络传输带宽以及 Kafka Broker 端的磁盘占用。
2.2、Broker 端
大部分情况下 Broker 从 Producer 端接收到消息后仅仅是原封不动地保存而不会对其进行任何修改。
但如下情况 Broker 端也可能进行压缩:
Broker 端指定了和 Producer 端不同的压缩算法
Broker 端也有一个参数叫 compression.type,若其指定了和 Producer 端不同的压缩算法,Broker 会将接收到的消息先解压缩,再按指定算法压缩。这会导致 Broker 端 CPU 使用率飙升。这个参数的默认值是 producer,表示 Broker 接收到消息后仅仅是原封不动地保存
3、何时解压缩?
有压缩必有解压缩!通常来说解压缩发生在消费者程序中,也就是说 Producer 发送压缩消息到 Broker 后,Broker 照单全收并原样保存起来。当 Consumer 程序请求这部分消息时,Broker 依然原样发送出去,当消息到达 Consumer 端后,由 Consumer 自行解压缩还原成之前的消息。
那么现在问题来了,Consumer 怎么知道这些消息是用何种压缩算法压缩的呢?其实答案就在消息中。Kafka 会将启用了哪种压缩算法封装进消息集合中,这样当 Consumer 读取到消息集合时,它自然就知道了这些消息使用的是哪种压缩算法。如果用一句话总结一下压缩和解压缩,那么我希望你记住这句话:Producer 端压缩、Broker 端保持、Consumer 端解压缩。
4、各种压缩算法对比
看一个压缩算法的优劣,有两个重要的指标:
- 压缩比,原先占 100 份空间的东西经压缩之后变成了占 20 份空间,那么压缩比就是 5,显然压缩比越高越好;
- 压缩 / 解压缩吞吐量,比如每秒能压缩或解压缩多少 MB 的数据。同样地,吞吐量也是越高越好。
从表中我们可以发现 zstd 算法有着最高的压缩比,而在吞吐量上的表现只能说中规中矩。反观 LZ4 算法,它在吞吐量方面则是毫无疑问的执牛耳者。当然对于表格中数据的权威性我不做过多解读,只想用它来说明一下当前各种压缩算法的大致表现。
在实际使用中,GZIP、Snappy、LZ4 甚至是 zstd 的表现各有千秋。但对于 Kafka 而言,它们的性能测试结果却出奇得一致,
- 在吞吐量方面:LZ4 > Snappy > zstd 和 GZIP;
- 在压缩比方面,zstd > LZ4 > GZIP > Snappy。
- 具体到物理资源,使用 Snappy 算法占用的网络带宽最多,zstd 最少,这是合理的,毕竟 zstd 就是要提供超高的压缩比;
- 在 CPU 使用率方面,各个算法表现得差不多,只是在压缩时 Snappy 算法使用的 CPU 较多一些,而在解压缩时 GZIP 算法则可能使用更多的 CPU。