Kafka-八股

目录

Kafka-基础架构

Kafka-文件存储机制

Kafka-保证数据可靠性

 Kafka-精确一次性

幂等性(Idempotence)---partition内部的exactly-once顺序语义

事务性--跨分区跨会话的Exactly-Once语义

Kafka消费策略

消费方式

消费策略

Range 范围分配策略(每个Topic计算一次)

RoundRobin 轮询分区策略(针对整个集群所有Topic进行计算)

StickyAssignor

Kafka如何实现高效读写

Kafka保证顺序写入

全局有序(不建议)

局部有序


Kafka 是一个分布式的基于发布/订阅模式消息队列(Message Queue),主要应用于大数据实时处理领域
 

分布式意味着Kafka需要保证数据的一致性同时可以保证数据的高可用 也就引出LEO和HW以及ISR

发布\订阅模式意味着Kafka需要维护一种生产消费模型 消费者组与Partition随之而来


Kafka-基础架构

一个Topic就是一个消息队列 将其划分成多份Partition 每个Partition的存储内容不同 它们一起才构成完整的Topic内容

(我们需要明确的是在数据还未到达时,Partition已经存在 并且有了Leader和Follower之分)

数据的产生和消费都面向的是Leader 当生产者数据到来时 流向相应的Partition(Leader)

Follow只是备份 以确保在Leader崩溃的时候可以选举出新的Leader并保证数据不丢失

然后该Leader再向其余的Partition(follower)同步数据


Kafka 中一个Topic可以拥有多个Partition Leader以供生产和消费 提高了并发能力


Kafka-文件存储机制

 

“.index”文件存储大量的索引信息,“.log”文件存储大量的数据,索引文件中的元
数据指向对应数据文件中 message 的物理偏移地址。


Kafka-保证数据可靠性

为保证 producer 发送的数据,能可靠的发送到指定的 topic, topic 的每个 partition 收到producer 发送的数据后,都需要向 producer 发送 ack(acknowledgement 确认收到),如果producer 收到ack, 就会进行下一轮的发送,否则重新发送数据。

数据在从Leader向Follower同步的过程中 必然会出现同步进度不一致的情况

有的Follower同步进度快 而有的慢一些

假设在同步数据的过程中 有一个follow因故障迟迟无法进行同步 难道此时Leader就要一直等下去么?

但是有的数据并不是很重要或者其对可靠性没有这么高的要求 所以Kafka设立了三种可靠性级别


 Kafka-精确一次性

Kafka的精确一次性分为分区内部以及跨分区实现

前者通过幂等性来实现 后者通过事务来实现

----------------------------------------------------------------------

本章主要讲的是生产者的Exactly-Once

消费者的精确一次性可以通过 让消费者保存消费到的Offset再结合上处理引擎来实现(Flink端到端的精确一次性消费)

幂等性(Idempotence)---partition内部的exactly-once顺序语义

幂等这个词原是数学领域中的概念,指的是某些操作或函数能够被执行多次,但每次得到的结果都是不变的

实现的关键就是为生产者的每条信息附带上[ProducerID][Topic+Partition]为Key的Value属性值(从0开始递增).这样一来 只用判断该value值就能知道该条信息是否重复或者乱序(等3的时候来了4 一下增加了2 说明中间有一条信息还未到达 )

但是问题也随之而来:

若producer 将一条信息重复发送给了多个分区 因为其Key值不同 造成了数据重复(跨分区);

若producer发生故障重启 必然会获得一个不同的producerID 也会有重复(跨会话)

这也就告诉我们 通过幂等性 只能实现同分区的精确一次性语义,而不能实现跨会话和跨分区的精确一次性

事务性--跨分区跨会话的Exactly-Once语义

当遇到上述幂等性的缺陷无法解决的时候,可以考虑使用事务了。事务可以支持多分区的数据完整性,原子性。并且支持跨会话的exactly once处理语义,也就是说如果producer宕机重启,依旧能保证数据只处理一次。

开启事务也很简单,首先需要开启幂等性,即设置enable.idempotence为true。然后对producer发送代码做一些小小的修改


Kafka消费策略

消费方式

consumer 采用 pull(拉) 模式从 broker 中读取数据。

push(推)模式很难适应消费速率不同的消费者,因为消息发送速率是由 broker 决定的。
它的目标是尽可能以最快速度传递消息,但是这样很容易造成 consumer 来不及处理消息,
典型的表现就是拒绝服务以及网络拥塞。而 pull 模式则可以根据 consumer 的消费能力以适
当的速率消费消息。

pull 模式不足之处是,如果 kafka 没有数据,消费者可能会陷入循环中, 一直返回空数
据。 针对这一点, Kafka 的消费者在消费数据时会传入一个时长参数 timeout,如果当前没有数据可供消费, consumer 会等待一段时间之后再返回,这段时长即为 timeout

消费策略

我们知道 Kafka消费是以组为单位来消费Topic 每个Topic被分成不同的Partition,而消费者组中又包含了多个消费者 所以我们需要使用消费策略 让Consumer明确自己需要消费那些Partititon

================================================

Kafka默认消费策略为Range+CooperativeSticky

Range 范围分配策略(每个Topic计算一次)

保证基本是均衡的
计算公式 :
n = 分区数/消费者数
m = 分区数%消费者数

前m个消费者,消费n+1个,剩余的消费n个

基本思想:均分之后 剩余未被消费的依次被消费(有点像轮询)

缺陷:

通过公式我们可以看出 一旦某个Topic的Partition数除不尽 Consumer0必然会多消费一个Partition

那如果有N多个Topic 那么Consumer0就必然会多(相较于组内其他消费者而言)消费N个Partition 这就会引起数据倾斜


RoundRobin 轮询分区策略(针对整个集群所有Topic进行计算)

RoundRobin 针对集群中 所有 Topic 而言 。 RoundRobin 轮询分区策略,是把所有的 partition 和所有的 consumer 都列出来 ,然后按照 hashcode 进行排序 ,最后通过轮询算法来分配 partition 给到各个消费者。

 缺点:

因为针对的是整个集群 而有的Consumer并没有订阅某些Topic

在轮询的过程中就会被隔过去 也会导致数据的不均匀

但是可以解决Range中数据倾斜问题(因为是在整个集群来分配而不是单个Topic)


StickyAssignor

虽然RoundRobin作出了改进 但因为其和Range 每一次分配过程都没有考虑上一次的分配结果

如果能考虑上一次分配的结果 尽量少的调整分区分配的变动 显然能节约开销

StickyAssignor分配策略:

        ① 分区的分配要尽可能的均匀;
        ② 分区的分配尽可能的与上次分配的保持相同。

当两者发生冲突时,第一个目标优先于第二个目标

StickyAssignor其实解决了RoundRobin在订阅不同Topic时 Rebalance后产生的消费不均衡问题

消费策略可以参考:

Kafka分区分配策略分析——重点:StickyAssignor - 杭州.Mark - 博客园

Kafka Range、RoundRobin、Sticky 三种 分区分配策略区别__lizhiqiang的博客-CSDN博客_sticky分配


Kafka如何实现高效读写

大家都知道是靠顺序读写磁盘和零拷贝

Kafka保证顺序写入

先不提高并发下保证顺序写入磁盘 先明确Kafka的普通写入模式

首先提出一个问题:生产者将消息投递到分区有没有规律?如果有,那么它是如何决定一条消息该投递到哪个分区的呢?

默认的分区策略

  • 如果在发消息的时候指定了分区,则消息投递到指定的分区

  • 如果没有指定分区,但是消息的key不为空,则基于key的哈希值来选择一个分区

  • 如果既没有指定分区,且消息的key也是空,则用轮询的方式选择一个分区

再思考一个问题:之前花费那么多的篇幅来讲broker的应答分级机制和精确一次性难道就不能保证数据的有序了?===> 当然不能 之前的那些措施都是在保证数据的不重复和保证不丢失

全局有序(不建议)

正因为数据会流向不同的分区 从而导致无序 所以可以只用一个生产者的同时每个Topic下面只设置一个分区 但是这样显然会降低效率

局部有序

Kafka的高并发高可用可以说离不开多Partition的设计 所以为了实现全局有序而只设置一个Partition显然是不可取的

要满足局部有序,只需要在发消息的时候指定partition key,kafka对其进行hash计算,根据计算结果决定放入哪个partition。这样partition key相同的消息会放在同一个partition(这里要注意可能发生的数据倾斜)此时,partition数量仍然可以设置多个,提升topic的整体吞吐量

在不增加partition数量的情况下想提高消费速度,可以考虑再次hash唯一标识(例如订单id)到不同的线程上,多个消费者小城并发处理消息(依旧可以保证局部有序)

【Kafka总结】Kafka 高效读写数据的原理_不断学习的克里斯的博客-CSDN博客_kafka读写原理

零拷贝

直观理解:Kafka零拷贝技术(Zero-Copy) - 简书

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值