大数据开发最火技术Kafka背后的“黑科技”

Kafka是由Apache软件基金会开发的一个开源流处理平台,被普遍地应用在数据缓冲、异步通讯、聚集日志、系统解耦等方面。相比较于其余常见消息系统,Kafka在保障了大部分功能特性的同时,还在高吞吐、低延迟等方面有很突出的表现。这篇文章不一样于其余介绍Kafka使用或实现的文章,只是谈谈Kafka用了什么“黑科技”使他在性能方面有这么突出的表现。web

消息顺序写入磁盘
磁盘大多数都仍是机械结构(SSD不在讨论的范围内),若是将消息以随机写的方式存入磁盘,就须要按柱面、磁头、扇区的方式寻址,寻址是一个“机械动做”也最耗时。为了提升读写硬盘的速度,Kafka就是使用顺序I/O。
2.png网络

图 1 Kafka顺序IOapp

上图中,每一个partition就是一个文件,每条消息都被append 到该 partition 中,属于顺序写磁盘,所以效率很是高。这种方法有一个缺陷—— 没有办法删除数据 ,因此Kafka是不会删除数据的,它会把全部的数据都保留下来,每一个消费者(Consumer)对每一个Topic都有一个offset用来表示读取到了第几条数据 。dom

关于磁盘顺序读写和随机读写的性能,引用一组Kafka官方给出的测试数据(Raid-5,7200rpm):异步

Sequence I/O: 600MB/ssocket

Random I/O: 100KB/s性能

因此经过只作Sequence I/O,给Kafka带来了性能的极大提高。测试

Zero Copy
考虑一个web程序读取文件内容并传输到网络的场景,实现的核心代码以下:
3.png
4.pngspa

图 2 普通read方法操作系统

虽然只是两个调用,但却通过了4次copy,其中有2次cpu copy,还有屡次用户态与内核态的上下文切换,这会加剧cpu的负担,而零拷贝就是为了解决这种低效。

mmap:

减小拷贝次数的一种方法是调用mmap()来代替read()调用:
图片1.png

应用程序调用mmap(),磁盘上的数据会经过DMA被拷贝到内核缓冲区,接着操做系统会把这段内核缓冲区与应用程序共享,这样就不须要把内核缓冲区的内容往用户空间拷贝。应用程序再调用write(),操做系统直接将内核缓冲区的内容拷贝到socket缓冲区中,最后再把数据发到网卡去。
图片2.png
图 3 mmap方法

使用mmap能够减小一次cpu copy,但也会遇到一些陷阱,当你的程序map了一个文件,可是当这个文件被另外一个进程截断(truncate)时, write系统调用会由于访问非法地址而被SIGBUS信号终止。一般能够经过,为SIGBUS信号创建信号处理程序或使用文件租凭(file leasing)的方式去解决,这里就再也不赘述了。

sendfile:

从2.1版内核开始,Linux引入了sendfile来简化操做

图片3.png
图片4.png

图 4 sendfile方法

sendfile() 方法引起 DMA 引擎将文件内容拷贝到一个读取缓冲区(DMA copy)而后由内核将数据拷贝到socket buffer(cpu copy)最后再拷贝到网卡(DMA copy)使用sendfile不只减小了数据拷贝的次数,还减小了上下文切换,数据传送始终只发生在kernel space

聊到这里,sendfile至少还须要一次cpu copy,那么这一步能不能省去呢?为了消除内核完成的全部数据复制,咱们须要一个支持收集(gather)操做的网络接口。同时,在内核版本2.4中,也修改了套接字缓冲区描述符以适应零拷贝要求。 这种方法不只减小了多个上下文切换,还彻底取消了cpu copy。
图片5.png
图 5 sendfile方法(DMA gather)

sendfile系统调用利用DMA引擎将文件内容拷贝到内核缓冲区去,而后将带有文件位置和长度信息的缓冲区描述符添加socket缓冲区去,这一步不会将内核中的数据拷贝到socket缓冲区中,DMA引擎会将内核缓冲区的数据拷贝到协议引擎中去,避免了最后一次CPU拷贝。

零拷贝技术很是广泛,JAVA的transferTo、transferFrom方法就是Zero Copy。

相关文章
相关标签/搜索