为什么Kafka速度那么快

作者: hedgehog1112 | 来源:发表于2019-06-22 15:17 被阅读9次

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

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

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

    一、写入数据

    优化写入速度用了两个技术, 顺序写入 和 MMFile 。

    1.1 顺序写入

    磁盘读写的快慢取决于你怎么使用它,也就是顺序读写或者随机读写。在顺序读写的情况下,某些优化场景磁盘的读写速度可以和内存持平(注:此处有疑问, 不推敲细节,参考 http://searene.me/2017/07/09/Why-is-Kafka-so-fast/)。

    硬盘是机械结构,每次读写都会寻址(“机械动作”最耗时)->写入,硬盘最讨厌随机I/O,喜欢顺序I/O。为提高读写硬盘速度,Kafka用顺序I/O。

    Linux对磁盘读写优化:read-ahead和write-behind,磁盘缓存等。在内存做这些操作,JAVA对象内存开销大,随着堆内存数据的增多,GC时间长,磁盘操作个好处:

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

        JVMGC效率低内存占用大磁盘可避免

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

    上图展示Kafka如何写入数据, 每个Partition都是一个文件收到消息后Kafka会把数据插入到文件末尾(虚框部分)。

    缺陷:不能删除数据 ,每个消费者(Consumer)对每个Topic都有一个offset表示 读到第几条数据 

    Consumer1有两个offset分别对应Partition0、Partition1(假设每一个Topic一个Partition);Consumer2有一个offset对应Partition2offset是由客户端SDK负责保存,Kafka的Broker完全无视这个东西的存在;一般情况下SDK会把它保存到zookeeper里面。(所以需要给Consumer提供zookeeper的地址)。

    解决:Kakfa删除数据策略:(1)基于时间,(2)基于partition文件大小(配置文档看具体配置)。

    1.2 Memory Mapped Files(mmap 内存映射文件 )

    出现原因:顺序写入硬盘,硬盘访问速度还是不可能追上内存。Kafka不是实时写入硬盘 ,利用了操作系统 分页存储(用内存提高I/O效率) 。

    工作原理:操作系统Page实现文件物理内存直接映射。对物理内存的操作会同步到硬盘(操作系统适当时)。64位操作系统中可表示20G数据文件

    用途:进程读写硬盘一样读写内存(当然是虚拟机内存),不必关心内存大小,虚拟内存兜底。

    好处:I/O提升, 省去用户空间内核空间 复制开销(调用文件的read会把数据先放到内核空间的内存中,然后再复制到用户空间的内存中。)

    缺点:不可靠, 写到mmap中的数据,没被真正写到硬盘,操作系统会在程序主动调用flush的时候才把数据真正写到硬盘。 

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

    二、读取数据

    基于sendfile实现Zero Copy

    2.1 传统模式文件传输流程(read/write方式):

    1.文件数据被copy到内核缓冲区(调read函数),2.然后到用户缓冲区(read函数返回),3.再到内核与socket相关缓冲区(write函数调用)

    4.相关协议引擎

    四次copy操作:硬盘—>内核buf—>用户buf—>socket相关缓冲区—>协议引擎

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

    2.2 简化网络上和两个本地文件之间的数据传输

    引入sendfile系统调用,减少数据复制、上下文切换。

    sendfile(socket, file, len)运行流程:

    1.文件数据被copy至内核缓冲区(sendfile系统调用),2.至内核中socket相关缓冲区,3.协议引擎

    减少到user缓冲区

    在apache,nginx,lighttpd等web服务器当中,都有一项sendfile相关的配置,提升文件传输性能。

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

    三、批量压缩

    系统瓶颈是网络IO不是CPU或磁盘,数据压缩消耗CPU资源少,

    批量压缩,多个消息一起压,如每个消息都压缩,压缩率低,

    Kafka用递归消息集合,传输并保持压缩格式(在日志中),直到被消费者解压缩

    Kafka支持多种压缩协议(Gzip和Snappy压缩协议)

    总结

    Kafka速度秘诀:

    (1)读取数据时配合sendfile直接暴力输出

    (2)写入数据:顺序写入,单个Partion是末尾添加所以速度最优。

    (3)批量压缩把所有消息变成一个批量文件,合理减少网络IO损耗,通过mmap提高I/O速度

    相关文章

      网友评论

        本文标题:为什么Kafka速度那么快

        本文链接:https://www.haomeiwen.com/subject/poxuqctx.html