众所周知kafka的资深吞吐量比一般的消息队列要高,号称the fastest,程序那他是员多因如何做到的,让我们从以下几个方面分析一下原因。年总 生产者(producer)是结解负责向Kafka提交数据的,我们先分析这一部分。吞吐 因为硬盘是年总机械结构,每次读写都会寻址->写入,结解其中寻址是吞吐一个“机械动作”,它是量高最耗时的。所以硬盘最“讨厌”随机I/O,资深最喜欢顺序I/O。为了提高读写硬盘的速度,Kafka就是使用顺序I/O。 上图就展示了Kafka是如何写入数据的,云南idc服务商每一个Partition其实都是一个文件,收到消息后Kafka会把数据插入到文件末尾(虚框部分) 。 上图中有两个消费者,Consumer1有两个offset分别对应Partition0、Partition1(假设每一个Topic一个Partition);Consumer2有一个offset对应Partition2。这个offset是由客户端SDK负责保存的,Kafka的Broker完全无视这个东西的存在;一般情况下SDK会把它保存到zookeeper里面。(所以需要给Consumer提供zookeeper的地址)。 即便是顺序写入硬盘,硬盘的访问速度还是服务器租用不可能追上内存。所以Kafka的数据并不是实时的写入硬盘,它充分利用了现代操作系统分页存储 来利用内存提高I/O效率。 通过mmap,进程像读写硬盘一样读写内存 (当然是虚拟机内存),也不必关心内存的大小有虚拟内存为我们兜底。 。Kafka提供了一个参数——producer.type来控制是不是主动flush,如果Kafka写入到mmap之后就立即flush然后再返回Producer叫同步(sync);写入mmap之后立即返回Producer不调用flush叫异步(async)。 Kafka使用磁盘文件还想快速?这是我看到Kafka之后的第一个疑问,ZeroMQ完全没有任何服务器节点,也不会使用硬盘,按照道理说它应该比Kafka快。可是实际测试下来它的速度还是被Kafka“吊打”。“一个用硬盘的比用内存的快 ”,这绝对违反常识;如果这种事情发生说明——它作弊了。 仔细想一下,一个Web Server传送一个静态文件,如何优化?答案是zero copy。传统模式下我们从硬盘读取一个文件是这样的 先复制到内核空间(read是系统调用,放到了DMA,所以用内核空间),然后复制到用户空间(1,2);从用户空间重新复制到内核空间(你用的socket是系统调用,所以它也有自己的内核空间),最后发送给网卡(3、4)。 Zero Copy中直接从内核空间(DMA的)到内核空间(Socket的) ,然后发送网卡。 Java的NIO提供了FileChannle,它的transferTo、transferFrom方法就是Zero Copy。 想到了吗?Kafka把所有的消息都存放在一个一个的文件中,当消费者需要数据的时候Kafka直接把“文件”发送给消费者。这就是秘诀所在,比如:10W的消息组合在一起是10MB的数据量,然后Kafka用类似于发文件的方式直接扔出去了,如果消费者和生产者之间的网络非常好(只要网络稍微正常一点10MB根本不是事。。。家里上网都是100Mbps的带宽了),10MB可能只需要1s。所以答案是——10W的TPS,Kafka每秒钟处理了10W条消息 。 out_fd作为输出(一般及时socket的句柄) in_fd作为输入文件句柄 off_t表示in_fd的偏移(从哪里开始读取) size_t表示读取多少个 没错,Kafka是用mmap作为文件读写方式的,它就是一个文件句柄,所以直接把它传给sendfile;偏移也好解决,用户会自己保持这个offset,每次请求都会发送这个offset。(还记得吗?放在zookeeper中的);数据量更容易解决了,如果消费者想要更快,就全部扔给消费者。如果这样做一般情况下消费者肯定直接就被压死了;所以Kafka提供了的两种方式——Push,我全部扔给你了,你死了不管我的事情;Pull,好吧你告诉我你需要多少个,我给你多少个。 Kafka速度的秘诀在于,它把所有的消息都变成一个的文件。通过mmap提高I/O速度,写入数据的时候它是末尾添加所以速度最优;读取数据的时候配合sendfile直接暴力输出。阿里的RocketMQ也是这种模式,只不过是用Java写的。 单纯的去测试MQ的速度没有任何意义,Kafka这种“暴力”、“流氓”、“无耻”的做法已经脱了MQ的底裤,更像是一个暴力的“数据传送器”。所以对于一个MQ的评价只以速度论英雄,世界上没人能干的过Kafka,我们设计的时候不能听信网上的流言蜚语——“Kafka最快,大家都在用,所以我们的MQ用Kafka没错”。在这种思想的作用下,你可能根本不会关心“失败者”;而实际上可能这些“失败者”是更适合你业务的MQ。生产者(写入数据)
顺序写入
Memory Mapped Files
消费者(读取数据)
如何提高Web Server静态文件的速度 ?
Kafka是如何耍赖的?
总结