大白话教你认识 Kafka,背后原理竟能秒懂?
一、Kafka 基础
消息系统的作用
1.Topic 主题
2.Partition 分区
Topic 和 partition 像是 HBASE 里的 table 和 region 的概念,table 只是一个逻辑上的概念,真正存储数据的是 region,这些 region 会分布式地存储在各个服务器上面,对应于kafka,也是一样,Topic 也是逻辑概念,而 partition 就是分布式存储单元。
这个设计是保证了海量数据处理的基础。我们可以对比一下,如果 HDFS 没有 block 的设计,一个 100T 的文件也只能单独放在一个服务器上面,那就直接占满整个服务器了,引入 block后,大文件可以分散存储在不同的服务器上。
注意:
-
分区会有单点故障问题,所以我们会为每个分区设置副本数
-
分区的编号是从0开始的
3.Producer – 生产者
4.Consumer – 消费者
5.Message – 消息
二、kafka的集群架构
Replica – 副本
Consumer Group – 消费者组
conf.setProperty("group.id","tellYourDream")
我们所熟知的一些消息系统一般来说会这样设计,就是只要有一个消费者去消费了消息系统里面的数据,那么其余所有的消费者都不能再去消费这个数据。可是 kafka 并不是这样,比如现在 consumerA 去消费了一个 topicA 里面的数据。 consumerA:
group.id = a
consumerB:
group.id = a
consumerC:
group.id = b
consumerD:
group.id = b
再让 consumerB 也去消费 TopicA 的数据,它是消费不到了,但是我们在 consumerC中重新指定一个另外的 group.id,consumerC 是可以消费到 topicA 的数据的。而consumerD 也是消费不到的,所以在 kafka 中,不同组可有唯一的一个消费者去消费同一主题的数据。 所以消费者组就是让多个消费者并行消费信息而存在的,而且它们不会消费到同一个消息,如下,consumerA,B,C是不会互相干扰的 consumer group:a
consumerA
consumerB
consumerC
如图,因为前面提到过了消费者会直接和leader建立联系,所以它们分别消费了三个leader,所以一个分区不会让消费者组里面的多个消费者去消费,但是在消费者不饱和的情况下,一个消费者是可以去消费多个分区的数据的。 Controller
熟知一个规律:在大数据分布式文件系统里面,95%的都是主从式的架构,个别是对等式的架构,比如 ElasticSearch。 kafka也是主从式的架构,主节点就叫controller,其余的为从节点,controller是需要和zookeeper 进行配合管理整个kafka集群。 kafka和zookeeper如何配合工作
kafka严重依赖于zookeeper集群(所以之前的zookeeper文章还是有点用的)。所有的broker在启动的时候都会往zookeeper进行注册,目的就是选举出一个controller,这个选举过程非常简单粗暴,就是一个谁先谁当的过程,不涉及什么算法问题。 那成为controller之后要做啥呢,它会监听zookeeper里面的多个目录,例如有一个目录/brokers/,其他从节点往这个目录上注册(就是往这个目录上创建属于自己的子目录而已)自己,这时命名规则一般是它们的id编号,比如/brokers/0,1,2 注册时各个节点必定会暴露自己的主机名,端口号等等的信息,此时controller就要去读取注册上来的从节点的数据(通过监听机制),生成集群的元数据信息,之后把这些信息都分发给其他的服务器,让其他服务器能感知到集群中其它成员的存在。 此时模拟一个场景,我们创建一个主题(其实就是在zookeeper上/topics/topicA这样创建一个目录而已),kafka会把分区方案生成在这个目录中,此时controller就监听到了这一改变,它会去同步这个目录的元信息,然后同样下放给它的从节点,通过这个方法让整个集群都得知这个分区方案,此时从节点就各自创建好目录等待创建分区副本即可。这也是整个集群的管理机制。 加餐时间
1.Kafka性能好在什么地方?
① 顺序写
操作系统每次从磁盘读写数据的时候,需要先寻址,也就是先要找到数据在磁盘上的物理位置,然后再进行数据读写,如果是机械硬盘,寻址就需要较长的时间。 kafka的设计中,数据其实是存储在磁盘上面,一般来说,会把数据存储在内存上面性能才会好。但是kafka用的是顺序写,追加数据是追加到末尾,磁盘顺序写的性能极高,在磁盘个数一定,转数达到一定的情况下,基本和内存速度一致随机写的话是在文件的某个位置修改数据,性能会较低。 ② 零拷贝
先来看看非零拷贝的情况 可以看到数据的拷贝从内存拷贝到 kafka 服务进程那块,又拷贝到socket缓存那块,整个过程耗费的时间比较高,kafka 利用了 Linux 的 sendFile 技术(NIO),省去了进程切换和一次数据拷贝,让性能变得更好。 2.日志分段存储
Kafka规定了一个分区内的.log文件最大为1G,做这个限制目的是为了方便把.log加载到内存去操作 00000000000000000000.index
00000000000000000000.log
00000000000000000000.timeindex
00000000000005367851.index
00000000000005367851.log
00000000000005367851.timeindex
00000000000009936472.index
00000000000009936472.log
00000000000009936472.timeindex
3.Kafka的网络设计
kafka的网络设计和Kafka的调优有关,这也是为什么它能支持高并发的原因
首先客户端发送请求全部会先发送给一个Acceptor,broker里面会存在3个线程(默认是3个),这3个线程都是叫做processor,Acceptor不会对客户端的请求做任何的处理,直接封装成一个个socketChannel发送给这些processor形成一个队列,发送的方式是轮询,就是先给第一个processor发送,然后再给第二个,第三个,然后又回到第一个。消费者线程去消费这些socketChannel时,会获取一个个request请求,这些request请求中就会伴随着数据。 线程池里面默认有8个线程,这些线程是用来处理request的,解析请求,如果request是写请求,就写到磁盘里。读的话返回结果。processor会从response中读取响应数据,然后再返回给客户端。这就是Kafka的网络三层架构。 所以如果我们需要对kafka进行增强调优,增加processor并增加线程池里面的处理线程,就可以达到效果。request和response那一块部分其实就是起到了一个缓存的效果,是考虑到processor们生成请求太快,线程数不够不能及时处理的问题。 所以这就是一个加强版的reactor网络线程模型。 finally
集群的搭建会再找时间去提及。这一篇简单地从角色到一些设计的方面讲述了Kafka的一些基础,在之后的更新中会继续逐步推进,进行更加深入浅出的讲解。
作者:说出你的愿望吧
链接:https://juejin.cn/post/6844903999066341384
10月26-27日,GOPS 全球运维大会 2023 · 上海站,来自国内互联网、金融证券、通信行业名企 80+大咖齐聚,还有农行、申万宏源证券、腾讯、字节等重磅专场,不可错过,心动不如行动~ 近期好文:
假没放够怎么办?你可以这样克服节后综合征
“高效运维”公众号诚邀广大技术人员投稿, 投稿邮箱:jiachen@greatops.net,或添加联系人微信:greatops1118. 点个“在看”,一年不宕机
发表评论