Kafka高性能设计_2

Kafka高性能设计_2

文章目录

1. 存储消息的性能优化手段

存储消息属于 Broker 端的核心功能

Kafka高性能设计_2

IO多路复用, 磁盘顺序写, page缓存, 分区分段结构

1.1 IO 多路复用

对于 Kafka Broker 来说,要做到高性能,首先要考虑的是:设计出一个高效的网络通信模型,用来处理它和 Producer 以及 Consumer 之间的消息传递问题。

SocketServer :
Kafka高性能设计_2
Kafka采用的是Reactor 网络通信模型

Kafka高性能设计_2
1 个 Acceptor 线程,负责监听新的连接,然后将新连接交给 Processor 线程处理。

N 个Processor 线程,每个 Processor 都有自己的 selector,负责从 socket 中读写数据。

N 个 KafkaRequestHandler 业务处理线程,它通过调用 KafkaApis 进行业务处理,然后生成 response,再交由给 Processor 线程。

Reactor 模式正是采用了很经典的 IO 多路复用技术, 它可以复用一个线程去处理大量的 Socket 连接,从而保证高性能。

1.2 磁盘顺序写

如何将消息快速地存储起来

Kafka 作为消息队列,本质上就是一个队列,是先进先出的,而且消息一旦生产了就不可变。这种有序性和不可变性使得 Kafka 完全可以「顺序写」日志文件,也就是说,仅仅将消息追加到文件末尾即可。

磁盘顺序写的性能远远高于磁盘随机写,甚至高于内存随机写。

Kafka高性能设计_2
对于普通的机械磁盘,如果是随机写入,性能确实极差,也就是随便找到文件的某个位置来写数据。但如果是顺序写入,因为可大大节省磁盘寻道和盘片旋转的时间,因此性能提升了 3 个数量级。

1.3 Page Cache

内存顺序写更快。

利用了操作系统本身的缓存技术,在读写磁盘日志文件时,其实操作的都是内存,然后由操作系统决定什么时候将 Page Cache 里的数据真正刷入磁盘。

Kafka高性能设计_2
age Cache 缓存的是最近会被使用的磁盘数据,利用的是「时间局部性」原理。

最近访问的数据很可能接下来再访问到。而预读到 Page Cache 中的磁盘数据,又利用了「空间局部性」原理,依据是:数据往往是连续访问的。

Kafka 作为消息队列,消息先是顺序写入,而且立马又会被消费者读取到。

页缓存还有一个巨大的优势:如果不用页缓存,而用jvm进程中的缓存的话, 对象的内存开销非常大。 此外还需要进行垃圾回收,GC 所带来的 Stop The World 问题也会带来性能问题。
1.对象的内存开销 2.jvm的gc的STW

1.4 分区分段结构

如果一个 Topic 只对应一个日志文件,显然只能存放在一台 Broker 机器上。

当面对海量消息时,单机的存储容量和读写性能肯定有限,这样又引出了又一个精妙的存储设计:对数据进行分区存储。

分区是Kafka 并发处理的最小粒度。很好的解决了存储是扩展问题。随着分区的增加,kafka的吞吐量会提升

kafka分区中有一个分段的概念, 分段对应的是日志文件:

Kafka高性能设计_2
每个 Partition 又被分成了多个 Segment。

如果不引入Segment的话, 文件会一直增大, 那么查找和维护不方便。

并且在历史删除时候, 必然需要把前面的内容删除, 引入segment后, 只需要把旧的segment文件删除, 保证了每一个segment的顺序写。

上一篇:Kafka高可用,高吞吐量低延迟的高并发的特性背后实现机制


下一篇:Kafka的生产者与消费者解析