部分内容参考:《kafka 权威指南》
1.发布订阅
1.1 前言
总所周知,kafka
是一个基于发布订阅模式的中间件,因此要想学习kafka
,先学习一下发布订阅模式。
1.2 介绍
发布订阅

简而言之就是,发布订阅模主要存在两个角色:
- 发布者
- 订阅者
发布者也叫消息的发送者,或者说叫消息的生产者,主要是用来生产消息和发送消息
生产者当生产完消息之后并不会直接把消息发送给消息的接收方,而是按照消息的类别发送到一个中间件里面
订阅者可以从中从中间件中接收感兴趣的消息,一旦发布者再次往中间件中发送消息,订阅者就会及时收到消息

真实例子
例如:现实生活中的订报纸,一般订报纸存在三种事务
- 报社
- 阅读者
- 报纸
报社(生产者)制造报纸内容,并且生产报纸(消息),当报纸生产完了交给邮局(中间件),邮局并不是把所有的报纸发给所有的人
邮局会把不同类型的报纸主动推送给向邮局订阅了的对应类型的阅读者(消费者)。一旦报社生产新的报纸,邮局还是会主动推送给阅读者,直到阅读者不再订阅。

模式优点
通过上述例子知道,发布订阅模式,通过一个中间件来解决生产者和消费者的耦合问题
如果没有中间件,生产者就会直接把消息发送给消费者,有了中间件,两者不直接通讯,从而达到了解耦

通过上图可知,这种模式工作原理如下:
- N个生产者在生产消息,同时N个消费者在消费消息,相互不通信而是中间件进行通信
- 生产者负责向中间件添加消息
- 消费者负责向中间件消费消息
一般来说中间件都是用队列来进行存储消息,因此消费消息也遵循先进先出的原理
中间件
中间件的作用有很多,大体如下:
-
生产者和消费者进行解耦
-
并发和忙先不均支持
消费者消费消息很慢,而生产者生产消息又很快,那么有了中间件以后
就可以同时启动多个消费者去进行消费.
同时未被消息的消息还会存储在中间件上,等生产者速度慢下来,消费者再去消费消息
当然向这种中间件称为消息中间件,市面上也有很多这样的消息中间件,例如:kafka
,RabbitMQ
,RocketMQ
在这里主要阐述kafka
,如果想要了解其他中间件可以参考这个地址
2.kafka介绍
2.1 历史
kafka
是一个由scala
和java
语言编写的一个高吞吐量的分布式发布订阅系统

kafka
最初使用场景就是一个日志系统,用来跟踪用户在网站的活动,例如,页面的访问次数和点击量或者是复杂的一些操作。这些操作记录下来,并且发送到kafka
,后端负责读取数据,·生成报告,为机器学习提供数据
2010年底宣布在GitHub
上作为开源项目进行发布,现在kafka
被很多组织用在了一些大型数据管道上
2.2 架构
在安装kafka
之前先来了解一些关于kafka
的一些架构,之后再去安装,会更加清楚
kafka
大体架构如下:

关于架构图的解释如下:
-
Broker
-
kafka
集群包含一个或者多个节点,每个节点称为broker
-
broker
是无状态的,因此需要通过zookeeper
来维护集群状态 - 一个
broker
可以每秒可以处理数十万次读写,且每个broker
都可以处理TB级别的消息而不影响性能
-
-
Topic
每个发布到
kafka
的消息都会有一个类别,类似于ElasticSearch
的Index
概念实际上每个
topic
消息是分开存储的,当在kafka
去创建topic
时,需要去指定partion
(分区),不同的分区存储同种类型的不同消息默认存储消息的时间为七天
-
Partion
每个
topic
都会有分区,类似于ElasticSearch
的索引分片原理,例如一个topic
里面有1000个消息,而这个topic
有4个分区,那就根据其自身的算法将1000个消息平均分割存储在四个分区上,如下image-20210509150427468
-
每个
topic
至少会分割一个或者多个partion
-
当生产者向中间件发送数据时,会根据分配策略,选择
partion
,然后将消息追加到partion
末尾从这句话可以看出
partion
的原理其实就是一个队列 -
每个消息在
partion
都会有自己自增的标号该标号的作用用来标识消息的顺序
同时用于标识消息的偏移量
例如,当在一个partion上消费了五条消息,当下次消费时就是从第六个消息开始消费,这个五就是偏移量
-
每个
partion
使用多个segment
文件存储数据 -
在一个
partion
中,消息数据是有序的,不同的partion
中的数据是无需的如果想要保证
kafka
里面topic
消息的有序性,那么就可以把该partion
设为1
-
-
Leader
-
为了保证数据的安全行,每个
partion
都会有其副本,其中只有一个会成为leader
(主),其他的会成为从follower
(从) -
leader
是负责数据的读写的partion
-
-
Follower
-
follower
不具备读写能力,只负责备份,这样就可以保证数据的一致性 -
所有的请求都是由
leader
完成,当leader
完成数据的变更操作时,就会广播给所有的follower
,然后follower
就会复制leader
变更的数据,从而保持同步 -
当然如果
leader
挂掉以后,则从follower
中从新选取一个新的leader
-
当然如果
follower
挂掉或者卡住,同步太慢,leader
就会从ISR
列表中删除,重新创建一个follower
关于ISR解释请参考这个地址
image-20210509160013583
注意:
为了保证数据的安全性,kafka集群会保证同一个
topic
的不同分区散落在不同的broker
上,具体策略如下:假设由
N
个broker
第 i 个
partion
分配到 (i mod n) 个broker
上
-
-
replication
-
如果
partion
损坏时,数据就会丢失,因此需要对数据进行备份,也就是设置partion
的replicatoin(副本)数字 -
一个分区可以有多个副本,当然kafka也不会让partion和他们的副本在一个
broker
上,因此也会散落在不同的broker
上具体策略如下:
假设由
N
个broker
第 i 个
partion
分配到(i mod n)
个broker
上第 i 个
partion
的 j 个 副本 分配到(i + j) mod n
个broker
上
-
-
producer
- 数据的发布者,主要发布消息到
kafka
的topic
中 -
broker
接受到消息后,会将当前的消息追加到当前用于追加数据的segment
文件中 - 发布者不需要指定发布到
topic
的那个分区上,topic
会根据规则自动将消息分配到某个分区上,当然也可以指定数据存储的partion
- 数据的发布者,主要发布消息到
-
consumer
- 消费者可以从
broker
中消费数据,同时一个消费者可以消费多个topic
中的数据
- 消费者可以从
-
consumer group
-
每个消费者都属于一个消费者组,一个消费者组可以拥有多个消费者,
一个消费者组对一个
topic
里面的消费消息只能读取一次当消息太多,消费者消费消息时间太长,那么就会造成阻塞,有了消费组以后
就可以往组里面增加多个消费者同时消费一个
topic
消息,这样就会提高速度
-
-
offset
image-20210509162125111
- offset记录着下一次消费者消费消息的序号,消费者通过偏移量来决定下次读取的消息
- 之前旧版本是将offset存储在
zookeepr
中,新版本则是存储在kafka
中 - 一个分区中,消息是按照顺序存储,每隔消息都有一个自增的id,这个id就是偏移量
- 消息被消费后不回立马删除,而是默认保存七天,这样很多业务可以重复读取
kafka
的数据 - 如果用户想要重复消费某个消息,那么可以控制偏移量来达到重复消费消息的功能
-
zookeeper
-
kafka
是通过zookeeper
来存储集群的元数据信息,例如topic
的数量多少,partion
多少等等数据
当然
kafka
也在想办法对zookeeper
进行剥离,因为维护两套集群成本较高 -
网友评论