二 kafka详解--kafka为什么快

前言Kafka 有多快呢?我们可以使用 OpenMessaging Benchmark Framework 测试框架方便地对 RocketMQ、Pulsar、Kafka、RabbitMQ 等消息系统进行对比测试 , 因为暂时没有测试条件(后续补上),我直接用这篇文章的测试结果(Benchmarking Kafka vs. Pulsar vs. RabbitMQ: Which is Fastest?) , 可以看到,在某种条件下,Kafka 写入速度比 RabbitMQ 快 15 倍,比 Pulsar 快 2 倍,在最高吞吐量下仍保持低延迟 。

二 kafka详解--kafka为什么快

文章插图
那么,为什么 Kafka 可以那么快呢?这里我先简单总结,后面会展开分析 。
  1. 从磁盘中顺序读写 event 。
  2. 通过批处理减少大量小 I/O 。
  3. 从文件到 socket 之间数据零拷贝 。
  4. 基于分区的横向扩展 。
ps:[本系列](博客后台 - 博客园 (cnblogs.com))博客将持续更新 。
顺序读写磁盘Kafka 严重依赖文件系统来读写 event 。我们不禁会问 , 磁盘不是很慢吗?Kafka 真的能提供很好的性能吗?
事实上,磁盘比人们预期的要慢得多,也快得多 , 这取决于它们的使用方式 。在这篇文章中(ACM Queue article)可以发现,在某些情况下,顺序磁盘访问可能比随机内存访问更快 。这要得益于现代操作系统对磁盘读写进行的大量的优化,包括 read-ahead 和 write-behind 技术 , 当我们顺序读取磁盘时,更多时候访问的不是磁盘,而是内存--pagecache 。
二 kafka详解--kafka为什么快

文章插图
因此,只要顺序访问文件系统,磁盘也可以很快 。Kafka 的 event 组织方式以及应用场景 , 天然地支持了顺序读写,并且 Kafka 也为此做了许多努力 , 例如批处理、追加写入等 。
【二 kafka详解--kafka为什么快】此外 , 相比主动将 event 维护在内存,采用文件系统还有以下好处:
  1. 可以缓存更多的数据 。在 JVM 中,维护对象的内存开销将是实际数据大小的两倍甚至更糟,随着堆内数据的增加,gc 将愈发频繁 。而使用文件系统可以在 pagecache 中缓存更多更紧凑的数据,而不需要考虑 gc 问题 。
  2. 重启后恢复更快 。由于数据缓存在 pagecache,进程重启,这部分缓存仍然可以保持 warn 的状态,如果在进程内存中维护这些数据的话,每次启动都需要重建(对于 10GB 缓存可能需要 10 分钟) 。
  3. 数据不会丢失 。如果数据维护在内存中 , 需要考虑定期将数据持久化到磁盘,一致性和性能的权衡将是一个比较麻烦的问题,即便如此,我们也不能保证数据不会丢失,例如 redis 可能损失几秒的数据,甚至更多 。在理论上,Kafka 就不会出现数据丢失的情况 。
  4. 大大简化了代码 。用于维护缓存和文件系统之间一致性的所有逻辑现在都在操作系统中,而操作系统往往更高效、更正确 。
通过批处理减少小I/O小 I/O 操作发生在客户端和服务端之间的数据传输以及服务端自身的持久化操作 。
为了避免小 I/O 操作,Kafka 是以批的形式来操作 event,而不是一次发送一条消息 。producer 会尝试在内存中积累数据,并在单个请求中发送更大的批 , 当然 , 这种方式是牺牲少量额外延迟以获得更好的吞吐量,我们可以配置累积数量和等待时间来平衡 。同理,consumer 读取数据时也会尝试一次读取更多 。
批处理可以产生较大顺序磁盘操作和连续内存块,不过也产生了较大的网络数据包,相应地,Kafaka 会将消息压缩后发送,当消息写入日志时仍然是压缩形式,仅由使用者解压缩 。
数据零拷贝另一个问题是过多的字节复制 。//zzs001
一般情况下,数据从文件传输到 socket 的数据路径为:磁盘 -》内核的 pagecache -》用户空间缓冲区 -》内核的 socket 缓冲区 -》NIC 缓冲区 。
二 kafka详解--kafka为什么快

文章插图
显然,这是非常低效的,有四个副本和两个系统调用 。Kafka 使用 sendfile,允许操作系统将数据从 pagecache 直接发送到网络,即磁盘 -》内核的 pagecache-》NIC 缓冲区 。从而避免这种重复复制和系统调用 。更多关于 sendfile 的内容可以参考Efficient data transfer through zero copy 。
二 kafka详解--kafka为什么快

文章插图

推荐阅读