kafka(二) 高性能技术分析
参考文章:
http://www.infoq.com/cn/articles/kafka-analysis-part-6
Partition提供并行处理的能力
Kafka是一个Pub-Sub的消息系统,无论是发布还是订阅,都须指定Topic。Topic只是一个逻辑的概念。每个Topic都包含一个或多个Partition,不同Partition可位于不同节点。同时Partition在物理上对应一个本地文件夹,每个Partition包含一个或多个Segment,每个Segment包含一个数据文件和一个与之对应的索引文件。在逻辑上,可以把一个Partition当作一个非常长的数组,可通过这个“数组”的索引(offset)去访问其数据。
一方面,由于不同Partition可位于不同机器,因此可以充分利用集群优势,实现机器间的并行处理。另一方面,由于Partition在物理上对应一个文件夹,即使多个Partition位于同一个节点,也可通过配置让同一节点上的不同Partition置于不同的disk drive上,从而实现磁盘间的并行处理,充分发挥多磁盘的优势。
利用多磁盘的具体方法是,将不同磁盘mount到不同目录,然后在server.properties中,将log.dirs设置为多目录(用逗号分隔)。Kafka会自动将所有Partition尽可能均匀分配到不同目录也即不同目录(也即不同disk)上。
虽然物理上最小单位是Segment,但Kafka并不提供同一Partition内不同Segment间的并行处理。因为对于写而言,每次只会写Partition内的一个Segment,而对于读而言,也只会顺序读取同一Partition内的不同Segment
client如何找到一条massage:
比如:要查找绝对offset为7的Message:
1)是用二分查找确定它是在哪个LogSegment中,自然是在第一个Segment中
2)打开这个Segment的index文件,也是用二分查找找到offset小于或者等于指定offset的索引条目中最大的那个offset。自然offset为6的那个索引是我们要找的,通过索引文件我们知道offset为6的Message在数据文件中的位置为9807
3)打开数据文件,从位置为9807的那个地方开始顺序扫描直到找到offset为7的那条Message
这套机制是建立在offset是有序的。索引文件被映射到内存中,所以查找的速度还是很快的
一句话,Kafka的Message存储采用了分区(partition),分段(LogSegment)和稀疏索引这几个手段来达到了高效性
Partition是最小并发粒度
多Consumer消费同一个Topic时,同一条消息只会被同一Consumer Group内的一个Consumer所消费。而数据并非按消息为单位分配,而是以Partition为单位分配,也即同一个Partition的数据只会被一个Consumer所消费(在不考虑Rebalance的前提下)。
ISR实现可用性与数据一致性的动态平衡
在CAP理论下,更多的是需要在可用性和一致性之间做权衡
常用数据复制及一致性方案
Master-Slave
- RDBMS的读写分离即为典型的Master-Slave方案
- 同步复制可保证强一致性但会影响可用性
- 异步复制可提供高可用性但会降低一致性
- WNR
- 主要用于去中心化的分布式系统中。DynamoDB与Cassandra即采用此方案或其变种
- N代表总副本数,W代表每次写操作要保证的最少写成功的副本数,R代表每次读至少要读取的副本数
- 当W+R>N时,可保证每次读取的数据至少有一个副本拥有最新的数据
- 多个写操作的顺序难以保证,可能导致多副本间的写操作顺序不一致。Dynamo通过向量时钟保证最终一致性
- Paxos及其变种
- Google的Chubby,Zookeeper的原子广播协议(Zab),RAFT等
- 基于ISR的数据复制方案
ISR,也即In-sync Replica。每个Partition的Leader都会维护这样一个列表,该列表中,包含了所有与之同步的Replica(包含Leader自己)
这个ISR是由Leader动态维护的。如果Follower不能紧“跟上”Leader,它将被Leader从ISR中移除,待它又重新“跟上”Leader后,会被Leader再次加加ISR中。每次改变ISR后,Leader都会将最新的ISR持久化到Zookeeper
可以通过request.required.acks 来设置同步复制or异步复制:
0 ,相当于异步发送,消息发送完毕即offset增加,继续生产
1,leader收到leader replica 对一个消息的接受ack才增加offset,然后继续生产
-1,leader收到所有replica 对一个消息的接受ack才增加offset,然后继续生产
优势:
1)由于Leader可移除不能及时与之同步的Follower,故与同步复制相比可避免最慢的Follower拖慢整体速度,也即ISR提高了系统可用性
2)ISR中的所有Follower都包含了所有Commit过的消息,而只有Commit过的消息才会被Consumer消费,故从Consumer的角度而言,ISR中的所有Replica都始终处于同步状态,从而与异步复制方案相比提高了数据一致性
3)ISR可动态调整,极限情况下,可以只包含Leader,极大提高了可容忍的宕机的Follower的数量。与Majority Quorum方案相比,容忍相同个数的节点失败,所要求的总节点数少了近一半。
顺序写磁盘
- 根据《一些场景下顺序写磁盘快于随机写内存》所述,将写磁盘的过程变为顺序写,可极大提高对磁盘的利用率。
- 数据删除,并非通过使用“读-写”模式去修改文件,而是将Partition分为多个Segment,每个Segment对应一个物理文件,通过删除整个文件的方式去删除Partition内的数据。这种方式清除旧数据的方式,也避免了对文件的随机写操作
充分利用Page Cache
- I/O Scheduler会将连续的小块写组装成大块的物理写从而提高性能
- I/O Scheduler会尝试将一些写操作重新按顺序排好,从而减少磁盘头的移动时间
- 充分利用所有空闲内存(非JVM内存)。如果使用应用层Cache(即JVM堆内存),会增加GC负担
- 读操作可直接在Page Cache内进行。如果消费和生产速度相当,甚至不需要通过物理磁盘(直接通过Page Cache)交换数据
- 如果进程重启,JVM内的Cache会失效,但Page Cache仍然可用
Broker收到数据后,写磁盘时只是将数据写入Page Cache,并不保证数据一定完全写入磁盘。从这一点看,可能会造成机器宕机时,Page Cache内的数据未写入磁盘从而造成数据丢失。但是这种丢失只发生在机器断电等造成操作系统不工作的场景,而这种场景完全可以由Kafka层面的Replication机制去解决。如果为了保证这种情况下数据不丢失而强制将Page Cache中的数据Flush到磁盘,反而会降低性能。也正因如此,Kafka虽然提供了flush.messages和flush.ms两个参数将Page Cache中的数据强制Flush到磁盘,但是Kafka并不建议使用
支持多Disk Drive
Broker的log.dirs配置项,允许配置多个文件夹。如果机器上有多个Disk Drive,可将不同的Disk挂载到不同的目录,然后将这些目录都配置到log.dirs里。Kafka会尽可能将不同的Partition分配到不同的目录,也即不同的Disk上,从而充分利用了多Disk的优势
零拷贝
Kafka中存在大量的网络数据持久化到磁盘(Producer到Broker)和磁盘文件通过网络发送(Broker到Consumer)的过程。这一过程的性能直接影响Kafka的整体吞吐量。
传统模式下的四次拷贝与四次上下文切换
以将磁盘文件通过网络发送为例。传统模式下,一般使用如下伪代码所示的方法先将文件数据读入内存,然后通过Socket将内存中的数据发送出去。
这一过程实际上发生了四次数据拷贝。首先通过系统调用将文件数据读入到内核态Buffer(DMA拷贝),然后应用程序将内存态Buffer数据读入到用户态Buffer(CPU拷贝),接着用户程序通过Socket发送数据时将用户态Buffer数据拷贝到内核态Buffer(CPU拷贝),最后通过DMA拷贝将数据拷贝到NIC Buffer。同时,还伴随着四次上下文切换。
sendfile和transferTo实现零拷贝
而Linux 2.4+内核通过sendfile系统调用,提供了零拷贝。数据通过DMA拷贝到内核态Buffer后,直接通过DMA拷贝到NIC Buffer,无需CPU拷贝。这也是零拷贝这一说法的来源。除了减少数据拷贝外,因为整个读文件-网络发送由一个sendfile调用完成,整个过程只有两次上下文切换,因此大大提高了性能。零拷贝过程如下图所示
减少网络开销
批处理
批处理是一种常用的用于提高I/O性能的方式。对Kafka而言,批处理既减少了网络传输的Overhead,又提高了写磁盘的效率。
1)Kafka 0.8.1及以前的Producer区分同步Producer和异步Producer。同步Producer的send方法主要分两种形式。一种是接受一个KeyedMessage作为参数,一次发送一条消息。另一种是接受一批KeyedMessage作为参数,一次性发送多条消息。而对于异步发送而言,无论是使用哪个send方法,实现上都不会立即将消息发送给Broker,而是先存到内部的队列中,直到消息条数达到阈值或者达到指定的Timeout才真正的将消息发送出去,从而实现了消息的批量发送。
2)Kafka 0.8.2开始支持新的Producer API,将同步Producer和异步Producer结合。虽然从send接口来看,一次只能发送一个ProducerRecord,而不能像之前版本的send方法一样接受消息列表,但是send方法并非立即将消息发送出去,而是通过batch.size和linger.ms控制实际发送频率,从而实现批量发送。
由于每次网络传输,除了传输消息本身以外,还要传输非常多的网络协议本身的一些内容(称为Overhead),所以将多条消息合并到一起传输,可有效减少网络传输的Overhead,进而提高了传输效率
数据压缩降低网络负载
Kafka从0.7开始,即支持将数据压缩后再传输给Broker。除了可以将每条消息单独压缩然后传输外,Kafka还支持在批量发送时,将整个Batch的消息一起压缩后传输。数据压缩的一个基本原理是,重复数据越多压缩效果越好。因此将整个Batch的数据一起压缩能更大幅度减小数据量,从而更大程度提高网络传输效率。
Broker接收消息后,并不直接解压缩,而是直接将消息以压缩后的形式持久化到磁盘。Consumer Fetch到数据后再解压缩。因此Kafka的压缩不仅减少了Producer到Broker的网络传输负载,同时也降低了Broker磁盘操作的负载,也降低了Consumer与Broker间的网络传输量,从而极大得提高了传输效率,提高了吞吐量。
高效的序列化方式
Kafka消息的Key和Payload(或者说Value)的类型可自定义,只需同时提供相应的序列化器和反序列化器即可。因此用户可以通过使用快速且紧凑的序列化-反序列化方式(如Avro,Protocal Buffer)来减少实际网络传输和磁盘存储的数据规模,从而提高吞吐率。这里要注意,如果使用的序列化方法太慢,即使压缩比非常高,最终的效率也不一定高
kafka(二) 高性能技术分析的更多相关文章
- YOLOV4各个创新功能模块技术分析(二)
YOLOV4各个创新功能模块技术分析(二) 四.数据增强相关-GridMask Data Augmentation 论文名称:GridMask Data Augmentation 论文地址:https ...
- Unity酱~ 卡通渲染技术分析(二)
前面的话 上一篇Unity酱~ 卡通渲染技术分析(一) 写了CharaMain.cginc,服装的渲染是怎么实现的.这篇来分析一下头发跟皮肤的实现 头发 本来以为unitychan的头发会有各向异性的 ...
- 闫燕飞:Kafka的高性能揭秘及优化
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文首发在云+社区,未经许可,不得转载. 大家下午好,我是来自腾讯云基础架构部ckafka团队的高级工程师闫燕飞.今天在这里首先为大家先分享 ...
- Linux内存技术分析(上)
Linux内存技术分析(上) 一.Linux存储器 限于存储介质的存取速率和成本,现代计算机的存储结构呈现为金字塔型.越往塔顶,存取效率越高.但成本也越高,所以容量也就越小.得益于程序访问的局部性原理 ...
- ActiveMQ、RabbitMQ、RocketMQ、Kafka四种消息中间件分析介绍
ActiveMQ.RabbitMQ.RocketMQ.Kafka四种消息中间件分析介绍 我们从四种消息中间件的介绍到基本使用,以及高可用,消息重复性,消息丢失,消息顺序性能方面进行分析介绍! 一.消息 ...
- 横向技术分析C#、C++和Java优劣
转自横向技术分析C#.C++和Java优劣 C#诞生之日起,关于C#与Java之间的论战便此起彼伏,至今不辍.抛却Microsoft与Sun之间的恩怨与口角,客观地从技术上讲,C#与Java都是对传统 ...
- 包建强的培训课程(3):App竞品技术分析
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...
- AOP技术分析
AOP的概述(http://www.cnblogs.com/lxp503238/p/6837653.html) 1. 什么是AOP的技术? * 在软件业,AOP为Aspec ...
- 【Python量化投资】基于技术分析研究股票市场
一 金融专业人士以及对金融感兴趣的业余人士感兴趣的一类就是历史价格进行的技术分析.维基百科中定义如下,金融学中,技术分析是通过对过去市场数据(主要是价格和成交量)的研究预测价格方向的证券分析方法. 下 ...
随机推荐
- Lumen 使用事件需要注意的事项
Lumen 版本 5.2 参考手册 laravel event 需要注意的事项 如果是第一次在lumen下使用事件,需要修改bootstrap\app.php文件 添加对EventServicePro ...
- xmlhttp.status的值及解释
100——客户必须继续发出请求 101——客户要求服务器根据请求转换HTTP协议版本 200——交易成功 201——提示知道新文件的URL 202——接受和处理.但处理未完成 203——返回信息不 ...
- 使用node写爬虫入门
最近看了node能做爬虫,所以就试了一下,一下是整个过程的记录 1.新建文件夹baidunews 2.在上边新建的文件夹下输入npm init进行初始化 3.初始化完成后下载需要的依赖包 npm in ...
- nodejs npm vue yarn 环境搭建
1.nodejs中文网http://nodejs.cn/download/下载最新版本 2.安装注意,虽然.msi包没有右键用管理员权限运行,如果直接双击安装可能会存在安装失败的问题.使用管理员权限运 ...
- js对数组array的常见操作小结
1.创建数组?两种方式 var arr = new Array("1","2","4"); var arr1 = ["1" ...
- 总结HTML5新增的标签及功能
https://my.oschina.net/chengkuan/blog/422306 标记意义及用法分析/示例 属性/属性值/描述 <article> 定义独立的内容,如论坛帖子.报纸 ...
- Ubuntu下的log日志查看器
1.lnav:Linux 下一个基于控制台的高级日志文件查看器 https://www.cnblogs.com/michealLang/p/9761886.html http://www.imooc. ...
- 【漏洞复现】PHPStudy后门
0x01 概述 Phpstudy软件是国内一款免费的PHP调试环境程序集成包,通过集成Apache.PHP.MySQL.phpMyAdmin.ZendOptimizer多款软件一次性安装,无需配置即可 ...
- (六)Kubernetes Pod控制器-ReplicaSet和Deployment和DaemonSet
Pod控制器相关知识 控制器的必要性 自主式Pod对象由调度器调度到目标工作节点后即由相应节点上的kubelet负责监控其容器的存活状态,容器主进程崩溃后,kubelet能够自动重启相应的容器.但对出 ...
- 执行shell脚本时提示/bin/sh^M: bad interpreter: No such file or directory
执行脚本时提示解释器有问题,错误提示如下: 这种提示一般是脚本在windows系统之通过记事本写的,记事本修改过的文本,会默认在文本前面加上一些看不到的标记,导致shell脚本不能被shell解释器识 ...