FCon7折倒计时最后一周:日程已上线70%!查看详情>>> 了解详情
写点什么

Kafka 凭什么速度那么快?

  • 2020-05-07
  • 本文字数:2597 字

    阅读完需:约 9 分钟

Kafka凭什么速度那么快?

Kafka 的消息是保存或缓存在磁盘上的,一般认为在磁盘上读写数据是会降低性能的,因为寻址会比较消耗时间,但是实际上,Kafka 的特性之一就是高吞吐率。


即使是普通的服务器,Kafka 也可以轻松支持每秒百万级的写入请求,超过了大部分的消息中间件,这种特性也使得 Kafka 在日志处理等海量数据场景广泛应用。


针对 Kafka 的基准测试可以参考,Apache Kafka 基准测试:每秒写入 2 百万(在三台廉价机器上)


下面从数据写入和读取两方面分析,为什么 Kafka 速度这么快。

一、写入数据

Kafka 会把收到的消息都写入到硬盘中,它绝对不会丢失数据。为了优化写入速度 Kafka 采用了两个技术, 顺序写入和 MMFile 。

1、顺序写入

磁盘读写的快慢取决于你怎么使用它,也就是顺序读写或者随机读写。在顺序读写的情况下,磁盘的顺序读写速度和内存持平。


因为硬盘是机械结构,每次读写都会寻址->写入,其中寻址是一个“机械动作”,它是最耗时的。所以硬盘最讨厌随机 I/O,最喜欢顺序 I/O。为了提高读写硬盘的速度,Kafka 就是使用顺序 I/O。


而且 Linux 对于磁盘的读写优化也比较多,包括 read-ahead 和 write-behind,磁盘缓存等。如果在内存做这些操作的时候,一个是 JAVA 对象的内存开销很大,另一个是随着堆内存数据的增多,JAVA 的 GC 时间会变得很长,使用磁盘操作有以下几个好处:


  • 磁盘顺序读写速度超过内存随机读写

  • JVM 的 GC 效率低,内存占用大。使用磁盘可以避免这一问题

  • 系统冷启动后,磁盘缓存依然可用


下图就展示了 Kafka 是如何写入数据的, 每一个 Partition 其实都是一个文件 ,收到消息后 Kafka 会把数据插入到文件末尾(虚框部分):



这种方法有一个缺陷——没有办法删除数据 ,所以 Kafka 是不会删除数据的,它会把所有的数据都保留下来,每个消费者(Consumer)对每个 Topic 都有一个 offset 用来表示读取到了第几条数据 。



两个消费者:


  • Consumer1 有两个 offset 分别对应 Partition0、Partition1(假设每一个 Topic 一个 Partition);

  • Consumer2 有一个 offset 对应 Partition2。


这个 offset 是由客户端 SDK 负责保存的,Kafka 的 Broker 完全无视这个东西的存在;一般情况下 SDK 会把它保存到 Zookeeper 里面,所以需要给 Consumer 提供 zookeeper 的地址。


如果不删除硬盘肯定会被撑满,所以 Kakfa 提供了两种策略来删除数据:


  • 一是基于时间;

  • 二是基于 partition 文件大小。


具体配置可以参看它的配置文档。

2、Memory Mapped Files

即便是顺序写入硬盘,硬盘的访问速度还是不可能追上内存。所以 Kafka 的数据并不是实时的写入硬盘 ,它充分利用了现代操作系统分页存储来利用内存提高 I/O 效率。


Memory Mapped Files(后面简称 mmap)也被翻译成 内存映射文件 ,在 64 位操作系统中一般可以表示 20G 的数据文件,它的工作原理是直接利用操作系统的 Page 来实现文件到物理内存的直接映射。


完成映射之后你对物理内存的操作会被同步到硬盘上(操作系统在适当的时候)。


通过 mmap,进程像读写硬盘一样读写内存(当然是虚拟机内存),也不必关心内存的大小有虚拟内存为我们兜底。


使用这种方式可以获取很大的 I/O 提升,省去了用户空间到内核空间复制的开销(调用文件的 read 会把数据先放到内核空间的内存中,然后再复制到用户空间的内存中。)


但也有一个很明显的缺陷——不可靠,写到 mmap 中的数据并没有被真正的写到硬盘,操作系统会在程序主动调用 flush 的时候才把数据真正的写到硬盘。


Kafka 提供了一个参数——producer.type 来控制是不是主动 flush,如果 Kafka 写入到 mmap 之后就立即 flush 然后再返回 Producer 叫 同步 (sync);写入 mmap 之后立即返回 Producer 不调用 flush 叫异步 (async)。

二、读取数据

Kafka 在读取磁盘时做了哪些优化?

2、基于 sendfile 实现 Zero Copy

传统模式下,当需要对一个文件进行传输的时候,其具体流程细节如下:


  • 调用 read 函数,文件数据被 copy 到内核缓冲区

  • read 函数返回,文件数据从内核缓冲区 copy 到用户缓冲区

  • write 函数调用,将文件数据从用户缓冲区 copy 到内核与 socket 相关的缓冲区。

  • 数据从 socket 缓冲区 copy 到相关协议引擎。


以上细节是传统 read/write 方式进行网络文件传输的方式,我们可以看到,在这个过程当中,文件数据实际上是经过了四次 copy 操作:


硬盘—>内核 buf—>用户 buf—>socket 相关缓冲区—>协议引擎


而 sendfile 系统调用则提供了一种减少以上多次 copy,提升文件传输性能的方法。


在内核版本 2.1 中,引入了 sendfile 系统调用,以简化网络上和两个本地文件之间的数据传输。sendfile 的引入不仅减少了数据复制,还减少了上下文切换。


sendfile(socket, file, len);
复制代码


运行流程如下:


  • sendfile 系统调用,文件数据被 copy 至内核缓冲区

  • 再从内核缓冲区 copy 至内核中 socket 相关的缓冲区

  • 最后再 socket 相关的缓冲区 copy 到协议引擎


相较传统 read/write 方式,2.1 版本内核引进的 sendfile 已经减少了内核缓冲区到 user 缓冲区,再由 user 缓冲区到 socket 相关缓冲区的文件 copy,而在内核版本 2.4 之后,文件描述符结果被改变,sendfile 实现了更简单的方式,再次减少了一次 copy 操作。


在 Apache、Nginx、lighttpd 等 web 服务器当中,都有一项 sendfile 相关的配置,使用 sendfile 可以大幅提升文件传输性能。


Kafka 把所有的消息都存放在一个一个的文件中,当消费者需要数据的时候 Kafka 直接把文件发送给消费者,配合 mmap 作为文件读写方式,直接把它传给 sendfile。

2、批量压缩

在很多情况下,系统的瓶颈不是 CPU 或磁盘,而是网络 IO,对于需要在广域网上的数据中心之间发送消息的数据流水线尤其如此。进行数据压缩会消耗少量的 CPU 资源,不过对于 kafka 而言,网络 IO 更应该需要考虑。


  • 如果每个消息都压缩,但是压缩率相对很低,所以 Kafka 使用了批量压缩,即将多个消息一起压缩而不是单个消息压缩

  • Kafka 允许使用递归的消息集合,批量的消息可以通过压缩的形式传输并且在日志中也可以保持压缩格式,直到被消费者解压缩

  • Kafka 支持多种压缩协议,包括 Gzip 和 Snappy 压缩协议

三、总结

Kafka 速度的秘诀在于,它把所有的消息都变成一个批量的文件,并且进行合理的批量压缩,减少网络 IO 损耗,通过 mmap 提高 I/O 速度,写入数据的时候由于单个 Partion 是末尾添加所以速度最优;读取数据的时候配合 sendfile 直接暴力输出。


本文转载自技术锁话公众号。


原文链接:https://mp.weixin.qq.com/s/5Mcs1zmoyB6b03c1NGotZA


2020-05-07 17:372438

评论

发布
暂无评论
发现更多内容

在线JSON转Schema工具

入门小站

工具

2022年购买服务器运维管理软件选择哪家好?

行云管家

IT运维 服务器运维

HTTPDNS 快速入门

37手游iOS技术运营团队

DNS httpdns

SpringMVC框架基础知识(01)

海拥(haiyong.site)

28天写作 12月日更

Greenplum内核源码分析-分布式事务(三)

王凤刚(ginobiliwang)

源码分析 分布式事务 greenplum

谁编写了区块链的规则?

CECBC

OceanBase 通过工信部电子标准院首批开源项目成熟度评估

OceanBase 数据库

数据库 工信部 OceanBase 开源

Xcode 配置多套 App 图标的方法 --- AppStore 图标 A/B Test 实践

37手游iOS技术运营团队

ios xcode appstore 产品页优化 自定产品页

大数据开发之Hive如何提高查询效率

@零度

大数据 hive

【签约计划第二季】百位签约创作者名单公布

InfoQ写作社区官方

签约计划第二季 热门活动

区块链赋能生猪养殖,让“猪”事有迹可循

CECBC

Veritas:2022年数据安全及合规领域行业预测

WorkPlus

常用的echo和cat,这次让我折在了特殊字符丢失问题上

华为云开发者联盟

Linux cat echo 特殊字符 定向

MongoDB按需物化视图介绍

MongoDB中文社区

mongodb

链计算、新基建:区块链助力数字经济新生态

CECBC

一个cpp协程库的前世今生(二)协程切换的原理

SkyFire

c++ 协程 cocpp

MongoDB基本介绍与安装(1)

Tom弹架构

Java mongodb

DTC 2021 | 一体化架构的原生分布式数据库正在成为核心系统首选

OceanBase 数据库

数据库 OceanBase 开源 OceanBase 社区版

COSCL开源评选名单公布!OceanBase 社区版荣获2021优秀开源项目奖

OceanBase 数据库

OceanBase 开源 OceanBase 社区版

Greenplum内核源码分析-分布式事务(一)

王凤刚(ginobiliwang)

源码分析 分布式事务 greenplum

云堡垒机和普通堡垒机的三大区别分析-行云管家

行云管家

云计算 网络安全 数据安全 堡垒机 云堡垒机

《国产分布式数据库选型及满意度调查报告》出炉,OceanBase获得双料第一

OceanBase 数据库

分布式数据库 OceanBase 开源 OceanBase 社区版

全国首个!OceanBase 助力江西省养老保险全国统筹信息系统上线

OceanBase 数据库

OceanBase 开源 OceanBase 社区版 核心系统

iOS 编译器__Attribute__的入门指南

37手游iOS技术运营团队

xcode LLVM Clang编译 Clang Attribute

Greenplum内核源码分析-分布式事务(二)

王凤刚(ginobiliwang)

源码分析 分布式事务 greenplum

2021MongoDB技术实践与应用案例征集活动获奖通知

MongoDB中文社区

☕【难点攻克技术系列】「海量数据计算系列」如何使用BitMap在海量数据中对相应的进行去重、查找和排序

洛神灬殇

BitMap bitmaps bitset 12月日更

取代Maven?maven-mvnd持续霸榜 GitHub Trending,性能提升300%

沉默王二

maven

回顾2021,展望2022 | TDengine一年“成绩”汇总

TDengine

数据库 tdengine 2021年终总结

forEach、map和for循环

编程江湖

大前端

旺链科技团建图鉴 | 认真工作,肆意生活~

旺链科技

区块链 企业文化 团建

  • 扫码添加小助手
    领取最新资料包
Kafka凭什么速度那么快?_行业深度_技术琐话_InfoQ精选文章