- kafka是一个
分布式
的基于发布/订阅模式的消息队列
(Message Queue),主要应用于大数据实时处理领域。
传统消息队列的应用场景
- 使用消息队列的好处:
-
解耦
:允许你独立地扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。
-
可恢复性
:系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。
-
缓冲
:有助于控制和优化数据流经过系统的速度,解决生产消息和消费消息的处理速度不一致的情况。
-
削峰
:在访问量剧增的情况下,使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。
-
异步通信
:很多时候用户不需要立即处理消息。消息队列提供了异步处理机制
,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。
- 消息队列的两种模式:
-
点对点模式
:一对一,消费者主动拉取
消息,消费者消费消息后,消息就被清除。队列支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费。
-
发布/订阅模式
:一对多,生产者生产消息放到队列中,队列推送消息
,消费者消费消息后,消息不会被清除。
点对点模式
发布/订阅模式(缺点:消费者长轮询)
kafka基础架构
-
Producer
:消息生产者,就是向 kafka broker 发消息的客户端;
-
Consumer
:消息消费者,向 kafka broker 取消息的客户端;
-
Consumer Group(CG)
:消费者组,由多个 consumer 组成。消费者组内每个消费者负责消费不同分区的数据,一个分区只能由一个组内某个消费者消费;消费者组之间互不影响。
所有的消费者都属于某个消费者组,即消费者组是逻辑上的一个订阅者。
-
Broker
:一台 kafka 服务器就是一个 broker。一个集群由多个 broker 组成。一个 broker可以容纳多个 topic。
-
Topic
: 可以理解为一个队列, 生产者和消费者面向的都是一个 topic;
-
Partition
: 为了实现扩展性,一个非常大的 topic 可以分布到多个 broker(即服务器)上,一个 topic 可以分为多个 partition,每个 partition 是一个有序的队列;
-
Replication
:副本,为保证集群中的某个节点发生故障时,该节点上的分区数据不丢失,且Kafka仍然能够继续工作, Kafka 提供了副本机制,一个 topic 的每个分区都有若干个副本,一个 leader 和若干个 follower。
-
Leader
: 每个分区多个副本的“主”,生产者发送数据的对象,以及消费者消费数据的对象都是 leader。
-
Follower
:每个分区多个副本中的“从”,实时从 leader 中同步数据,保持和 leader 数据的同步。 leader 发生故障时,某个 Follower 会成为新的 leader。
kafka工作流程
- kafka中消息是以
topic
进行分类的,producer
生产消息,consumer
消费消息,都是面向topic的。(从命令行操作看出)
-
topic
是逻辑上的概念,而partition
是物理上的概念,每个partition
对应于一个log文件,该 log 文件中存储的就是producer 生产的数据。(topic = N partition,partition = log)
kafka文件存储机制
- 由于生产者生产的消息会不断追加到
.log
文件末尾, 为防止.log
文件过大导致数据定位效率低下,kafka采取了分片
和索引
机制,将每个partition
分为多个segment
。每个segment
对应两个文件——.index
文件和.log
文件。 这些文件位于一个文件夹下,该文件夹的命名规则为:topic name+分区序号
。例如:first-topic
这个topic有三个分区,则其对应的文件夹为first-topic-0
,first-topic-1
,first-topic-2
。
00000000000000000000.index
00000000000000000000.log
00000000000000170410.index
00000000000000170410.log
00000000000000239430.index
00000000000000239430.log
.index文件和.log文件的结构示意图
-
.index
和.log
文件以当前segment
的第一条消息的offset
命名。.index
文件存储大量的索引信息,.log
文件存储大量的数据,索引文件中的元数据指向对应数据文件中message
的物理偏移地址。
- 主题分区的原因:
-
方便在集群中扩展
,每个partition
可以通过调整以适应它所在的机器,而一个topic
又可以有多个partition
组成,因此整个集群就可以适应适合的数据了;
-
可以提高并发
,因为可以以partition
为单位进行读写了。
- 分区的原则:
- 指明
partition
的情况下,直接将指明的值作为partiton
值;
- 没有指明
partition
值但有key
的情况下,将key
的 hash 值与 topic 的 partition 总数进行取余得到的partition
值;
- 既没有
partition
值又没有 key 值的情况下,第一次调用时随机生成一个整数(后面每次调用在这个整数上自增),将这个值与 topic 可用的 partition 总数取余得到 partition值,即round-robin
算法。
生产者发送数据分装为ProducerRecord对象的API
- 生产者数据可靠性保证:为保证
producer
发送的数据,能可靠地发送到指定的 topic, topic 的每个partition
收到producer 发送的数据后,都需要向 producer 发送ack
(acknowledgement:确认收到),若producer收到 ack,则会进行下一轮的发送,否则重新发送数据。
生产者数据可靠性保证机制
- 何时发送ack?确保有
follower
与leader
同步完成,leader
再发送ack
,这样才能保证leader
挂掉之后,能在follower
中选举出新的leader
。
- 多少个follower同步完成之后发送ack?①半数以上的follower同步完成,即可发送ack;②全部的follower同步完成,才可以发送ack。
序号 |
方案 |
优点 |
缺点 |
1 |
半数以上完成同步,就发送ack |
延迟低 |
选举新的 leader 时,容忍 n 台节点的故障,需要 2n+1 个副本。容错率:1/2。 |
2 |
全部完成同步,才发送ack |
选举新的 leader 时, 容忍 n 台节点的故障,需要 n+1 个副本。容错率:1。 |
延迟高 |
- kafka选取了第二种方案,原因:①为了容忍 n 台节点的故障,第一种方案需要 2n+1 个副本,而第二种方案只需要 n+1 个副本,又 kafka 的每个分区都有大量的数据, 因此,第一种方案会造成大量数据的冗余。②虽然第二种方案的网络延迟会比较高,但网络延迟对 kafka 的影响较小。
- kafka采用第二种方案之后,设想以下情景: leader 收到数据,所有 follower 都开始同步数据,但有一个 follower,因为某种故障迟迟不能与 leader 进行同步,那 leader 就要一直等下去,直到它完成同步,才能发送 ack。这个问题怎么解决呢?
- leader 维护了一个动态的
in-sync replica set(ISR)
,意为和 leader 保持同步的 follower 集合。当 ISR 中的 follower 完成数据的同步之后,就会给 leader 发送 ack。若follower长时间未向leader同步数据,则该follower将被踢出ISR,该时间阈值由replica.lag.time.max.ms
参数设定。当leader 发生故障之后,就会从 ISR 中选举新的 leader。
-
replica.lag.time.max.ms
:If a follower hasn't sent any fetch requests or hasn't consumed up to the leaders log end offset for at least this time, the leader will remove the follower from isr。TYPE: long。DEFAULT: 10000。
- 若对数据的可靠性要求不是很高,能够容忍少量数据的丢失,则没必要等 ISR 中的 follower 全部接收成功,因此,kafka 为用户提供了三种可靠性级别,用户根据对可靠性和延迟的要求进行权衡,选择以下配置:
-
0
:producer
不等待 broker 的 ack,这一操作提供了一个最低的延迟,broker
一接收到还没有写入磁盘就已经返回,当 broker 故障时有可能丢失数据;
-
1
:producer
等待 broker 的 ack,partition
的 leader 落盘成功后返回才ack,若在 follower同步成功之前 leader 故障,则将会丢失数据;
-
-1
(all):producer
等待 broker 的 ack,partition
的 leader 和 ISR 的follower 全部落盘成功后才返回 ack。但若在 follower 同步完成后,broker 发送 ack 之前, leader 发生故障,则会造成数据重复。
acks=1
acks=-1
- 助记:返ACK前,0无落盘,1一落盘,-1全落盘,(落盘:消息存到本地)
- kafka数据一致性
-
LEO(Log End Offset)
:每个副本的最后一个offset。
-
HW(High Watermark)
:高水位,指消费者能见到的最大的offset,ISR 队列中最小的 LEO。
网友评论