kafka原理学习笔记

一、kafka简介

kafka是分布式消息队列,具有高性能、持久化、多副本备份、横向扩展能力,其最大的特性是高吞吐量、低延迟,可以几乎实时的处理大量数据。这和其文件存储机制的设计有关,简单来说写入时为顺序写入,且有MMFile的机制,而在检索时,也做了分段和稀疏索引。同时,在整体架构上,对于同一个topic中的消息会均匀的分布在不同的partition上,也使得分布式消费成为可能。

二、鸟瞰kafka

kafka overview.jpg

总体来讲,kafka的数据流向如上图所示,简单描述流程大概是:
2.1 producer往topic上写消息,此时kafka会均匀的把message分布在不同的partition上(发送时不需要指定partition,kafka会自动的loan balance),同时写入时只写入到了leader上
2.2 leader发送给其他的follower
2.3 各个consumer线程可以组成一个consumer group,每个consumer group 均可以从头开始消费一个topic下的各个partition,即同一个topic的message,允许多个consumer group进行消费
2.4 在某一个consumer group 进行消费时,partition中每一条message只能被其中的一个consumer线程消费
2.5 消费时可是从leader进行的消费
2.6 Consumer处理partition里面的message的时候是顺序读取的。所以必须维护着上一次读到哪里的offsite信息
2.7 broker、topics、partitions的一些元信息用zk来存,监控和路由啥的也都会用到zk

好了,到这里一定会产生一些疑问,比如:
1.partition是干嘛的?
2.为什么不同的consumer group 可以同时消费同一个topic?如何确保消费顺序?
3.leader 和 follower的设计是有什么用?
4.消息的可靠性?
5.为什么说kafka的性能很好,读写很快?

一个个来看。

三、Topic & partition

Topic相当于传统消息系统MQ中的一个队列queue,producer端发送的message必须指定是发送到哪个topic,但是不需要指定topic下的哪个partition,因为kafka会把收到的message进行load balance,均匀的分布在这个topic下的不同的partition上( hash(message) % [broker数量] )。物理上存储上,这个topic会分成一个或多个partition,每个partiton相当于是一个子queue。在物理结构上,每个partition对应一个物理的目录(文件夹),文件夹命名是[topicname][partition][序号],一个topic可以有无数多的partition,根据业务需求和数据量来设置。在kafka配置文件中可随时更高num.partitions参数来配置更改topic的partition数量,在创建Topic时通过参数指定parittion数量。Topic创建之后通过Kafka提供的工具也可以修改partiton数量。

一般来说,(1)一个Topic的Partition数量大于等于Broker的数量,可以提高吞吐率。(2)同一个Partition的Replica尽量分散到不同的机器,高可用。

当add a new partition的时候,partition里面的message不会重新进行分配,原来的partition里面的message数据不会变,新加的这个partition刚开始是空的,随后进入这个topic的message就会重新参与所有partition的load balance。

四、消息写入及顺序消费

kafka中的Message是以topic为基本单位组织的,不同的topic之间是相互独立的。每个topic又可以分成几个不同的partition(每个topic有几个partition是在创建topic时指定的),每个partition存储一部分Message。

另外,因为硬盘是机械结构,每次读写都会寻址->写入,其中寻址是一个“机械动作”,它是最耗时的。所以硬盘最讨厌随机I/O,最喜欢顺序I/O。为了提高读写硬盘的速度,kafka就是使用顺序I/O。

也就是说,当有消息写入时,实际的写入会类似下图所示

kafka数据写入图.jpg

可以看到,message在partition中是顺序存储的,这种方式有一个很明显的缺陷——没有办法删除数据,所以kafka是不会删除数据的,它会把所有的数据都保留下来。所以消费时需要consumer通过offset来标记消费到了那一条数据,通过的consumer group中的consumer消费的offset可能不一样,如下图所示


kafka消费.png

五、leader选举机制

从前文的鸟瞰图我们可以知道,kafka的每个partition可以在其他的kafka broker节点上存副本,即对于同一个partition可以有一个leader多个follower,这是为了确保当某个broker宕机的时候不会影响这个kafka集群,如果是leader所在的broker宕机了,也会有新的follower站出来成为leader,也就是leader的重新选举机制。那kafka是如何进行leader的重新选举的呢?

1.kafka会在所有的broker中选出一个controller,所有partition的leader选举都由controller决定,controller在zk注册Watch,一旦有broker宕机,其在zk对应的znode会自动被删除,zk会fire controller注册的watch

2.此时controller会去重新读取一遍最新的幸存的broker,并决定partition集合(set_p),这个集合包含了宕机的broker上所有的partition

3.对于集合中的每个partition,controller会去读取该partition的ISR(副本同步队列),如果当前ISR中有至少一个replica(副本)还幸存,则选择其中一个作为新leader,新的ISR则包含当前ISR中所有幸存的replica(选举算法的实现类似于微软的PacificA)。如果该partition的所有replica都宕机了,则将新的leader设置为-1。

4.将新的leader,ISR和新的leader_epoch及controller_epoch写入/brokers/topics/[topic]/partitions/[partition]/state。

5.直接通过RPC向set_p相关的broker发送LeaderAndISRRequest命令。

如下图所示


kafka leader选举机制.jpg

从前文的鸟瞰图我们可以知道,producer发送消息时是先写到leader上,再由leader同步到follower,如果写到leader后还没同步时正好broker宕机了,此时重新选举后follower充当新的leader,则刚刚那条消息的数据就丢失了,也就是说kafka在一些少量场景下存在丢失数据的可能(消息队列消费时也同样存在丢失数据或者重复消费的场景),接下来就来看下kafka在消息可靠性上的设置

六、消息的可靠性

6.1生产者生产消息的可靠性

消息投递可靠性.jpg

6.2消费者消费时可能存在的异常场景

6.2.1 consumer的delivery gurarantee,默认是读完message先commmit再处理message,autocommit默认是true,这时候先commit就会更新offsite+1,一旦处理失败,offsite已经+1,这个时候就会丢message

6.2.2 如前文所述,同一个topic支持被不同的consumer group消费,如果同样的业务存在两个consumer group(一般不会这样),在消息消费时就需要考虑重复消费的场景

6.3由于MMFile导致的消息丢失

kafka为了像操作内存一样写入数据,在写入数据时,除了前文提到的顺序写入外,也会有内存映射文件(Memory Mapped Files ,MMFile)这样的机制,它的工作原理是直接利用操作系统的Page来实现文件到物理内存的直接映射。完成映射之后你对物理内存的操作会被同步到硬盘上,如果在完成同步之前,服务器宕机了,则也会丢失一部分数据。

七、kafka如何做到快速写入和读取的

7.1 快速写入

关于写入的部分前文已经提到,主要是依靠顺序写入避免了最耗时的机械动作——寻址,以及上面刚刚提到的MMFile机制可以使kafka如同操作内存一样的写入。

7.2 快速读取

7.2.1 parition数据文件

为了弄明白kafka如何做到快速读取某一条消息的,首先要看一下partition文件的结构。

kafka文件存储方式.jpg

partition是以文件的形式存储在文件系统中。

Partition中的每条Message由offset来表示它在这个partition中的偏移量,这个offset不是该Message在partition数据文件中的实际存储位置,而是逻辑上一个值,它唯一确定了partition中的一条Message。因此,可以认为offset是partition中Message的id。partition中的每条Message包含了以下三个属性:

offset
MessageSize
data

其中offset为long型,MessageSize为int32,表示data有多大,data为message的具体内容

7.2.2 分段

由于consumer消费消息时一定是根据偏移量(offset)顺序消费的,弄清楚了partition文件的结构后,所以很容易想到kafka解决查询效率的手段之一是将数据文件分段。

比如有100条Message,它们的offset是从0到99。假设将数据文件分成5段,第一段为0-19,第二段为20-39,以此类推,每段放在一个单独的数据文件里面,数据文件以该段中最小的offset命名。这样在查找指定offset的Message的时候,用二分查找就可以定位到该Message在哪个段中。

7.2.3 索引

数据文件分段使得可以在一个较小的数据文件中查找对应offset的message了,但是这依然需要顺序扫描才能找到对应offset的message。为了进一步提高查找的效率,kafka为每个分段后的数据文件建立了索引文件。

索引包含两个部分(均为4个字节的数字),分别为相对offset和position。

相对offset:因为数据文件分段以后,每个数据文件的起始offset不为0,相对offset表示这条message相对于其所属分段的数据文件中最小的offset的大小。举例,分段后的一个数据文件的offset是从20开始,那么offset为25的message在index文件中的相对offset就是25-20 = 5。

position:表示该条message在数据文件中的绝对位置。只要打开文件并移动文件指针到这个position就可以读取对应的message了。

值得一提的是,index文件中并没有为数据文件中的每条message建立索引,而是采用了稀疏存储的方式,每隔一定字节的数据建立一条索引。这样避免了索引文件占用过多的空间,从而可以将索引文件保留在内存中。但缺点是没有建立索引的message也不能一次定位到其在数据文件的位置,从而需要做一次顺序扫描,但是这次顺序扫描的范围就很小了。

八、参考及引用的资料

8.1 Kafka史上最详细原理总结 ----看完绝对不后悔 https://blog.csdn.net/lingbo229/article/details/80761778

8.2 震惊了!原来这才是kafka! https://www.jianshu.com/p/d3e963ff8b70

8.3 kafka leader选举机制原理 https://www.jianshu.com/p/1f02328a4f2e

8.4 http://kafka.apache.org/documentation/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容