首页 > 代码库 > 漫游Kafka设计篇之性能优化
漫游Kafka设计篇之性能优化
Kafka视频教程同步首发,欢迎观看。
Kafka在提高效率方面做了非常大努力。Kafka的一个主要使用场景是处理站点活动日志,吞吐量是非常大的。每一个页面都会产生好多次写操作。读方面,如果每一个消息仅仅被消费一次,读的量的也是非常大的。Kafka也尽量使读的操作更轻量化。
我们之前讨论了磁盘的性能问题,线性读写的情况下影响磁盘性能问题大约有两个方面:太多的琐碎的I/O操作和太多的字节拷贝。I/O问题发生在client和服务端之间,也发生在服务端内部的持久化的操作中。
消息集(message set)
为了避免这些问题,Kafka建立了“消息集(message set)”的概念,将消息组织到一起。作为处理的单位。以消息集为单位处理消息,比以单个的消息为单位处理,会提升不少性能。Producer把消息集一块发送给服务端。而不是一条条的发送;服务端把消息集一次性的追加到日志文件里,这样降低了琐碎的I/O操作。consumer也能够一次性的请求一个消息集。
另外一个性能优化是在字节拷贝方面。在低负载的情况下这不是问题,可是在高负载的情况下它的影响还是非常大的。
为了避免这个问题,Kafka使用了标准的二进制消息格式,这个格式能够在producer,broker和producer之间共享而无需做不论什么修改。
zero copy
Broker维护的消息日志不过一些文件夹文件,消息集以固定队的格式写入到日志文件里。这个格式producer和consumer是共享的,这使得Kafka能够一个非常重要的点进行优化:消息在网络上的传递。现代的unix操作系统提供了高性能的将数据从页面缓存发送到socket的系统函数,在linux中,这个函数是sendfile.
为了更好的理解sendfile的优点,我们先来看下一般将数据从文件发送到socket的数据流向:
- 操作系统把数据从文件拷贝内核中的页缓存中
- 应用程序从页缓存从把数据拷贝自己的内存缓存中
- 应用程序将数据写入到内核中socket缓存中
- 操作系统把数据从socket缓存中复制到网卡接口缓存,从这里发送到网络上。
这显然是低效率的,有4次拷贝和2次系统调用。
Sendfile通过直接将数据从页面缓存发送网卡接口缓存,避免了反复拷贝,大大的优化了性能。
在一个多consumers的场景里,数据只被复制到页面缓存一次而不是每次消费消息的时候都反复的进行拷贝。这使得消息以近乎网络带宽的速率发送出去。
这样在磁盘层面你差点儿看不到不论什么的读操作,由于数据都是从页面缓存中直接发送到网络上去了。
这篇文章具体介绍了sendfile和zero-copy技术在Java方面的应用。
数据压缩
非常多时候,性能的瓶颈并不是CPU或者硬盘而是网络带宽。对于须要在数据中心之间传送大量数据的应用更是如此。当然用户能够在没有Kafka支持的情况下各自压缩自己的消息,可是这将导致较低的压缩率。由于相比于将消息单独压缩,将大量文件压缩在一起才干起到最好的压缩效果。
Kafka採用了端到端的压缩:由于有“消息集”的概念,client的消息能够一起被压缩后送到服务端,并以压缩后的格式写入日志文件,以压缩的格式发送到consumer,消息从producer发出到consumer拿到都被是压缩的,仅仅有在consumer使用的时候才被解压缩,所以叫做“端到端的压缩”。
Kafka支持GZIP和Snappy压缩协议。
更具体的内容能够查看这里。
漫游Kafka设计篇之性能优化