Kafka使用经验(3)—Kafka性能解剖

Kafka使用心得(3)—Kafka性能解剖

Kafka技术介绍

 

1. PULL VS PUSH

 

      pull和push是两种消息传输方式,各有优缺点。Flume采用了push的方式进行消息传输,对注册后的客户端,主动发送收到的消息。而Kafka采用了传统的消息队列的方式,生产者使用push方式,消费者使用pull方式。

       对于生产者来说,Kafka集群的处理能力要远远超过自己,因此可以很放心的进行push。而对于消费者来说,Kafka可以同时支持不同的消费者组,而不同消费者的处理能力也不尽相同,因此为了减轻系统复杂度,对于消费者Kafka采用了pull方式。

 

2.  消息持久化

 

Kafka将消息持久化到磁盘,传统观念上磁盘的速度非常慢,对于追求高吞吐量的系统来说使用磁盘并不是明智的选择。但Kafka仍然选择了磁盘,并且实现了高速的读写。主要有以下几个原因:

  • 消息使用Append进行写
  • 读取消息的时间复杂度为O(1)
  • 读写的过程使用了mmap
  • ZeroCopy
  • 支持消息压缩

2.1 Append写

 

实验证明,磁盘速度慢的原因是因为寻道耗时非常大,但顺序读写的速度是非常快的,Kafka设计的一个重要优点在于消息的顺序读写。



 

从图中能看到,每次写消息,都是向文件尾部进行追加的。

 

2.2 消息读取时间复杂度

 

Kafka所有文档介绍时间复杂度是O(1),它的消息存储结构为:

 



 

消息目录下存储着以topic-partitionId命名的目录,每个目录下存储按照一定规则切割的segment文件。文件名为第一个消息的offset.kafka。

 

每条消息内容为:消息头+magic+crc+body。

 

读取的时候给定一个offset,可以从zk获取到对应的消息文件,通过计算offset和文件名的差值,可以算出来偏移量,根据消息的大小定位出消息的地址。

 

2.3 ZeroCopy

 

 kafka的消息存储和读取使用了cache技术,每次是先写到cache,每隔一定时间或者达到一定量会flush到磁盘。使用了mmap技术。

 

Linux使用了分页管理,mmap技术将文件直接映射到内存中的多个页上面,用户对文件的操作,直接转化为对内存的操作。

 

传统方式的数据访问:


 

需要经历2个阶段,首先从磁盘将数据读到缓存,之后再从缓存将数据copy到进程的用户态内存。

 

mmap的数据访问:


 

mmap实际上会让进程直接访问cache,因为mmap函数,会将缓存映射到进程的地址空间,然后进程即可直接访问。

 

2.4 Zero-Copy

 

Zero-Copy是一种提升Web文件读取速度的技术。首先看一下传统的Web Server文件发送方式:

 



 

其中数据会经历4次Copy,4次上下文切换。其中2次Copy都需要CPU参与。

 

而Zero-Copy技术则是:

 



 

 只需要3次Copy,和2次上下文切换就能完成数据发送,CPU只需要参与一次Copy。

 

优化:

 

 其实还有一种进一步优化方案是合并Read buffer和socket buffer

 

2.5 压缩

 

现实中,Kafka性能的瓶颈在于带宽,经过测试发现,在不断读取消息的过程中,经常会出现网卡被打满的情况。因此压缩技术对Kafka的性能非常重要。Kafka采用了端到端的压缩方式。

 

客户端的消息可以一起被压缩后送到服务端,并以压缩后的格式写入日志文件,以压缩的格式发送到consumer,消息从producer发出到consumer拿到都被是压缩的,只有在consumer使用的时候才被解压缩,所以叫做“端到端的压缩”。

 

支持GZip和Snappy协议

相关内容推荐