Kafka——性能逆天的存在

Kafka——性能逆天的存在

(by 刘延允,2016-12-17)

0、引言

Kafka是LinkedIn开源出来的一款消息服务器,用scala语言实现;这货的性能是百万级的QPS(估计是挂载了多块磁盘),我随便写个测试程序就是十万级。

1、Kafka基本概念

在Kafka中消息是按照Topic进行分类的;每条发布到Kafka集群的消息都有一个类别,这个类别被称为Topic。(物理上不同Topic的消息分开存储,逻辑上一个Topic的消息虽然保存于一个或多个broker上但用户只需指定消息的Topic即可生产或消费数据而不必关心数据存于何处)。

每个Topic包含一个或多个Parition;Parition是物理存储上的概念,创建Topic时可指定Parition数量。每个Parition对应一个存储文件夹,文件夹下存储该Parition所持有的消息数据和索引文件。Topic进行分区划分的主要目的是出于性能方面的考虑,Kafka尽量的使所有分区均匀的分布到集群所有的节点上而不是集中在某些节点上,另外主从关系也尽量均衡,这样每个节点都会担任一定比例的分区的Leader。每个Parition是一个有序的队列,每条消息在Parition中拥有一个offset。

消息的发布者可将消息发布到指定的Topic中,同时Producer也能决定将此消息发送到哪个Parition(也可以采取随机、哈希、轮训等策略)。

消息的消费者主动从Kafka中拉取消息进行消费(pull模式),在Kafka中一个Parition中的消息可以被无限多个消费者进行消费,每个消费者之间是完全独立,每个Consumer消费后的消息Kafka并不进行删除操作,Kafka中的消息删除是定期进行的,可以指定保留多长时间消息不被删除。通过指定offset就可以消费任意位置的消息,当然前提是指定的offset是存在的。从这点上看Kafka更像是一个只能追加、不能修改、支持随机读取的小文件管理系统。

上面提到每个Consumer是完全独立,如果多个Consume想轮流消费同一个Topic的同一个Parition就做不到;后来Kafka发明了一个Consumer-group的概念,每个Consumer客户端被创建时,会向Zookeeper注册自己的信息;一个group中的多个Consumer可以交错的消费一个Topic的所有Paritions;简而言之,保证此Topic的所有Paritions都能被此group所消费,且消费时为了性能考虑,让Parition相对均衡的分散到每个Consumer上,Consume-group之间是完全独立。主人的相反是挺好的,但是悲剧的是客户端基本都不支持,貌似只有java的客户端支持比较好。

2、消息顺序性与可靠性设计

发布到Kafka的消息在一个Parition中是顺序存储的,发布者可以通过随机、哈希、轮训等方式发布到多个分区中,消费者通过指定offset进行消费;所以Kafka当中消息的顺序性更多的取决于使用方如何使用。

Kafka系统中消息支持容灾备份存储,每个Parition有主分区、备用分区的概念,一个Topic中的多个Parition的主分区可能落在不同的物理机器上面,Kafka也是尽量让其分布在不同的机器上以提高系统性能。消息的读写都是通过主分区直接完成,客户端要直连主分区所在的物理机进行读写操作。备用分区就像一个"Consumer"消费主分区的消息并保存在本地日志中进行备份;主分区负责跟踪所有的备用分区的状态,如果备用分区"落后"太多或者失效,主分区将会把它从同步列表中删除;主备分区的管理是通过zookeeper进行的。

发布时的可靠性取决于两点:发送端的确认机制、以及Kafka系统落地的策略。发送端支持无确认、主分区确认(主分区收到消息后发送确认回执)、以及主备分区确认(备用分区消息同步后主分区才发送确认回执)三种机制;Kafka系统落地的策略有两种刷盘方式:通过配置消息数、以及配置刷盘时间间隔。

消费时的可靠性取决于消费者的读取逻辑,Kafka是不保存消息的任何状态的。At most once、At least once 、Exactly
once 三种模式需要自己按照业务实现,最容易实现就是At least once,两外两种在分布式系统中都不可能做到完全的绝对实现,只能无限靠近,降低错误率。

3、消息存储方式

Parition是以文件的形式存储在文件系统中,比如创建了一个名为tipocTest的Topic,其有4个Parition,在Kafka的数据目录下面会有四个文件夹,按照Topic-partnum命名。

每个文件夹的内容

Parition中的每条Message由offset来表示它在这个Parition中的偏移量,这个offset不是该Message在Parition数据文件中的实际存储位置,而是逻辑上一个值,它唯一确定了Parition中的一条Message。因此,可以认为offset是Parition中Message的id。Parition中的每条Message包含了三个属性: Offset 、DataSize 、Data;Parition的数据文件则包含了若干条上述格式的Message,按offset由小到大排列在一起;Kafka收到新的消息后追加到文件末尾即可,所以消息的发布效率是很高的。

下面我们来思考另一个问题,如果一个Parition只有一个数据文件会怎么样? 新消息是添加在文件末尾,不论文件数据文件有多大,这个操作永远都是O(1)。但是在读取的时候根据offset查找Message是顺序查找的,因此,如果数据文件很大的话,查找的效率就低。那么Kafka是如何解决查找效率的的问题呢?1)
分段、2) 索引。

4、数据文件的分段与索引

Kafka解决查询效率的手段之一是将数据文件分段,可以配置每个数据文件的最大值,每段放在一个单独的数据文件里面,数据文件以该段中最小的offset命名。这样在查找指定offset的Message的时候,用二分查找就可以定位到该Message在哪个段中。

数据文件分段使得可以在一个较小的数据文件中查找对应offset的Message了,但是这依然需要顺序扫描才能找到对应offset的Message。为了进一步提高查找的效率,Kafka为每个分段后的数据文件建立了索引文件,文件名与数据文件的名字是一样的,只是文件扩展名为.index。索引文件中包含若干个索引条目,每个条目表示数据文件中一条Message的索引——Offset与position(Message在数据文件中的绝对位置)的对应关系;index文件中并没有为数据文件中的每条Message建立索引,而是采用了稀疏存储的方式,每隔一定字节的数据建立一条索引。这样避免了索引文件占用过多的空间,从而可以将索引文件保留在内存中。但缺点是没有建立索引的Message也不能一次定位到其在数据文件的位置,从而需要做一次顺序扫描,但是这次顺序扫描的范围就很小了。

每个分段还有一个.timeindex索引文件,这个文件的格式与.index文件格式一样,所记录的东西是消息发布时间与offset的稀疏索引,用于消息定期删除使用。

下图是一个分段索引的例子

这套机制是建立在offset是有序的;索引文件被映射到内存中,所以查找的速度还是很快的。一句话,Kafka的Message存储采用了分区(Parition)、分段(segment)和稀疏索引这几个手段来达到高效发布和随机读取。

5、消费端设计

出于性能、容灾方面的考虑,实际需求是有多Consumer消费一个Topic的情况;由于多个Consumer之间是相互独立的,可以采用竞争Parition上岗的方式进行消费,同一个时刻只有一个Consumer在消费一个Parition,多个Consumer之间定期同步offset状态;如果是需要多通道消费,可以竞争不同的Parition对应资源上岗消费。

由于Kafka是按照offset进行读取的,一般的client都封装成:给定一个起始offset后续不停的get就可以顺序读取了,没有消费确认的概念,Kafka也不会维护每个消息、每个Consumer的状态。其实实现一套消费确认机制也不难,这需要我们实现一个proxy层,在proxy层保留一个循环缓冲区,业务端消费确认后方可从缓冲区里面移除,如果一段时间没有确认,下次来取的时候重复下发下去,类似于tcp滑动窗口的概念。

时间: 2024-11-10 07:29:34

Kafka——性能逆天的存在的相关文章

Kafka—性能逆天的存在

0.引言 Kafka是LinkedIn开源出来的一款消息服务器,用Scala语言实现:这货的性能是百万级的QPS(估计是挂载了多块磁盘),我随便写个测试程序就是十万级. 1.Kafka基本概念 在Kafka中消息是按照Topic进行分类的:每条发布到Kafka集群的消息都有一个类别,这个类别被称为Topic.(物理上不同Topic的消息分开存储,逻辑上一个Topic的消息虽然保存于一个或多个broker上但用户只需指定消息的Topic即可生产或消费数据而不必关心数据存于何处). 每个Topic包

Apache kafka性能优化架构分析

应用程序优化:数据压缩 consumer offset默认情况下是定时批量更新topics的partitions offset值 Apache kafka性能优化架构分析

Kafka性能调优

Kafka的配置详尽.复杂,想要进行全面的性能调优需要掌握大量信息,这里只记录一下我在日常工作使用中走过的坑和经验来对kafka集群进行优化常用的几点. 1.JVM的优化 java相关系统自然离不开JVM的优化.首先想到的肯定是Heap Size的调整. vim bin/kafka-server-start.sh      调整KAFKA_HEAP_OPTS="-Xmx16G -Xms16G"的值 推荐配置:一般HEAP SIZE的大小不超过主机内存的50%. 2.网络和ios操作线程

Kafka设计解析(五)- Kafka性能测试方法及Benchmark报告

本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/2015/12/31/KafkaColumn5_kafka_benchmark 摘要 本文主要介绍了如何利用Kafka自带的性能测试脚本及Kafka Manager测试Kafka的性能,以及如何使用Kafka Manager监控Kafka的工作状态,最后给出了Kafka的性能测试报告. 性能测试及集群监控工具 Kafka提供了非常多有用的工具,如Kafka设计解析(三)- Kafka High Avail

kafka性能基准测试

转载请注明出处:http://www.cnblogs.com/xiaodf/ 1.测试环境 该benchmark用到了六台机器,机器配置如下 l  IntelXeon 2.5 GHz processor with six cores l  Six7200 RPM SATA drives l  32GB ofRAM l  1GbEthernet 这6台机器其中3台用来搭建Kafka broker集群,另外3台用来安装Zookeeper及生成测试数据.6个drive都直接以非RAID方式挂载.实际上

Kafka性能调优分析-线上环境篇

一.背景介绍: 在平时的开发中,使用kafka来发送数据已经非常熟悉,但是在使用的过程中,其实并没有比较深入的探索kafka使用过程中 一些参数配置,带来的损失可能就是没有充分的发挥出kfka的优势,无法很好的满足业务场景.在意识这个问题后,专门腾出 时间来总结一下kakfa参数配置的调优,以充分发挥kafka在低时延,高吞吐等不同场景下的优势. 二.通用介绍: -------- 生产者配置 ------- 常规参数设置解析: Properties props = new Properties(

Kafka测试及性能调优详细总结

Kafka性能测试 测试背景 由于业务需求,针对kafka在不同参数下的性能进行测试.从而进行kafka性能调优 测试目标 测试kafka 0.8n的性能(Producer/Consumer性能).当消息大小.批处理大小.压缩等参数变化时对吞吐率的影响. 测试环境 软件版本:kafka 0.8.1.1 硬件环境:3台多云服务组成的kafka集群.各服务器CPU4核,内存16G,配置如下: 服务器IP: 203.150.54.215 203.150.54.216 203.150.54.217 测试

为了追求极致的性能,Kafka掌控了这11项要领

很多同学私信问我Kafka在性能优化方面做了哪些举措,对于相关问题的答案其实我早就写过了,就是没有系统的整理一篇,最近思考着花点时间来整理一下,下次再有同学问我相关的问题我就可以潇洒的甩个链接了.这个问题也是Kafka面试的时候的常见问题,面试官问你这个问题也不算刁难你.在网上也有很多相关的文章开讲解这个问题,比如之前各大公众号转载的“为什么Kafka这么快?”,这些文章我看了,写的不错,问题在于只是罗列了部分的要领,没有全部的详述出来.本文所罗列的要领会比你们网上搜寻到的都多,如果你在看完本篇

rabbitMQ、activeMQ、zeroMQ、Kafka、Redis 比较

Kafka作为时下最流行的开源消息系统,被广泛地应用在数据缓冲.异步通信.汇集日志.系统解耦等方面.相比较于RocketMQ等其他常见消息系统,Kafka在保障了大部分功能特性的同时,还提供了超一流的读写性能. 针对Kafka性能方面进行简单分析,相关数据请参考:https://segmentfault.com/a/1190000003985468,下面介绍一下Kafka的架构和涉及到的名词: Topic:用于划分Message的逻辑概念,一个Topic可以分布在多个Broker上. Parti