kafka基础原理

架构:

副本的相同分区位置不能存在于同一个broker上, 没有意义,当机器出现故障的时候,这个副本就没有问题.
在这里插入图片描述

offset,topic,partitions的介绍:

在这里插入图片描述

Kafka 中消息是以 topic 进行分类的,生产者生产消息,消费者消费消息,都是面向 topic的。

topic 是逻辑上的概念,而 partition 是物理上的概念,每个 partition 对应于一个 log 文件(这个log文件不是指的日志文件,而是真正的数据),该 log 文件中存储的就是 producer 生产的数据。Producer 生产的数据会被不断追加到该log 文件末端,且每条数据都有自己的 offset。消费者组中的每个消费者,都会实时记录自己消费到了哪个offset,以便出错恢复时,从上次的位置继续消费。

kafka文件存储机制

在这里插入图片描述

一个segment file中有多个segment , 一个segment由 .index和.log文件组成, 为防止每个文件过大, 查找效率过低,所以会有多个segment, 每个的segment文件应该是500M

通过offset查找message:
例如读取offset=368776的message,需要通过下面2个步骤查找。
第一步查找segment file

上图为例,其中00000000000000000000.index表示最开始的文件,起始偏移量(offset)为0.第二个文件00000000000000368769.index的消息量起始偏移量为368770 = 368769 + 1.同样,第三个文件00000000000000737337.index的起始偏移量为737338=737337 + 1,其他后续文件依次类推,以起始偏移量命名并排序这些文件,只要根据offset二分查找文件列表,就可以快速定位到具体文件。
当offset=368776时定位到00000000000000368769.index|log

第二步通过segment file查找message

通过第一步定位到segment file,当offset=368776时,依次定位到00000000000000368769.index的元数据物理位置和00000000000000368769.log的物理偏移地址,然后再通过00000000000000368769.log顺序查找直到offset=368776为止

offset的解释:

由于 consumer 在消费过程中可能会出现断电宕机等故障,consumer 恢复后,需要从故障前的位置的继续消费,所以 consumer 需要实时记录自己消费到了哪个 offset,以便故障恢复后继续消费。

Kafka 0.9 版本之前,consumer 默认将 offset 保存在 Zookeeper 中,从 0.9 版本开始, consumer 默认将 offset 保存在 Kafka 一个内置的 topic 中,该 topic 为 consumer_offsets。1

注: offset的存储主要是按照(GTP[组,主题, 分区]来进行确定offset的,如果不按照组进行offset,每个消费者在进行消费的时候是会出现数据重复问题的)

API:

配置: auto.offset.reset 3个属性: [latest, earliest, none]
latest : 默认配置,offset为最新的数据的位置
earliest : 为最早的, 恢复上次的消息的消费的offset位置
none : 找不到偏移量的时候, 抛出异常

找不到偏移量的情况(none会报异常):

1 . 没有初始化的偏移量的情况
2. 当前偏移量在服务器上不再存在时(例如,因为数据已经被删除)

注意:

  1. 这个offset是按照消费者组进行划分的,而不是按照消费者
  2. offset这个值在外部时,只有当消费者启动的时候才会去访问, 内存中也存在一份, 如果每条数据都需要与外部的offset进行访问, 效率就太低了, 默认是offset自动提交,每隔一段时间,将内存中的offset进行更新到外部

消费者的可靠性维护

因为消费者的消息是持久化的,当机器宕机故障的时候会读取offset , 所以需要保证offset的可靠.
自动提交:

enable.auto.commit:是否开启自动提交 offset 功能
auto.commit.interval.ms:自动提交 offset 的时间间隔

当数据正处于处理时间的时候, 这时候正好达到offset的自动提交时间, offset提交,但是数据还没有处理完成,这时候的机器宕机,便会造成数据的丢失.

手动提交:

手动提交又分为同步提交(comminsync)和异步提交(commitasync)

同步提交: 阻塞线程,会有自动失败重试 ,但效率较低
异步提交: 效率快,但会有数据丢失问题

问题: 先提交 offset 后消费,有可能造成数据的漏消费;而先消费后提交 offset,有可能会造成数据的重复消费。

自定义offset:
思路: 要想解决上面问题, 可以使用MySQL的事务,来完成数据的提交和处理的同步.

后面会过来更新这个的代码操作…

分区

分区的原因:
提高并发性,提高运行效率
分区的原则:

(1)没有指明 partition 值但有 key 的情况下,将 key 的 hash 值与 topic 的 partition
数进行取余得到 partition 值
(2)既没有 partition 值又没有 key 值的情况下,第一次调用时随机生成一个整数( 后面每次调用在这个整数上自增),将这个值与 topic 可用的 partition 总数取余得到partition值,也就是常说的 round-robin 算法。 (轮询)

生产者发送数据的可靠性

为了保证可靠性: 当发送成功时,会返回ack
在这里插入图片描述

当发送leader中, ISR的follower 全部同步完成之后,会返回ack消息,提示消息应答成功.

两种副本同步机制:
在这里插入图片描述

ISR机制:
情景: kafka采用的是第二种, 可能会出现当某一个follower因为某些故障,一直处于等待状态,就没有办法去发送ack应答 .

机制:

Leader 维护了一个动态的 in-sync replica set (ISR),意为和 leader 保持同步的 follower 集合。当 ISR 中的 follower 完成数据的同步之后,leader 就会给 follower 发送 ack。如果 follower长时间 未 向 leader 同 步 数 据 , 则 该 follower 将 被 踢 出 ISR ,该 时 间 阈 值 由replica.lag.time.max.ms 参数设定。Leader 发生故障之后,就会从 ISR 中选举新的 leader

最开始的ISR是有两个判断条件的,一个是时间阈值, 一个是消息相差,后来因为可能出现当批数据发送,直接出现相差过多,每次的相差

ack 应答机制:
三种可靠级别(因为有的数据丢掉不重要):

0:producer 不等待 broker 的 ack,这一操作提供了一个最低的延迟,broker 一接收到还没有写入磁盘就已经返回,当 broker 故障时有可能丢失数据;
1:producer 等待broker 的 ack,partition 的 leader 落盘成功后返回ack,如果在 follower
同步成功之前leader 故障,那么将会丢失数据;
-1(all):producer 等待 broker 的 ack,partition 的 leader 和 follower 全部落盘成功后才
返回 ack。但是如果在 follower 部分消息同步完成,broker 发送 ack 之前,leader 发生故障,那么会造成数据重复(这时候的重复数据就是之前的follower的部分消息同步的区域)。
也可能造成数据丢失: 当ISR中没有其他的follower,且这个时候leader发生故障

HW和LEO:

在这里插入图片描述
LEO:指的是每个副本最大的 offset;
HW:指的是消费者能见到的最大的 offset,ISR 队列中最小的 LEO。

leader 发生故障之后:

会从 ISR 中选出一个新的 leader,之后,为保证多个副本之间的
数据一致性,其余的 follower 会先将各自的 log 文件高于 HW 的部分截掉,然后从新的 leader同步数据

follower 发生故障之后:

follower 发生故障后会被临时踢出 ISR,待该 follower 恢复后,follower 会读取本地磁盘记录的上次的HW,并将 log 文件高于 HW 的部分截取掉,从 HW 开始向 leader 进行同步。
等该 follower 的 LEO 大于等于该 Partition 的 HW,即 follower 追上 leader 之后,就可以重
新加入 ISR 了

Exactly Once 语义

作用: 解决了同一生产者发送相同重复数据问题,但只解决了同一生产者问题(PID)

根据<PID, Partition, SeqNumber> 这三个值来判断是否相同

ACK 级别为0 :只发送一次,但是会出现丢失数据
ACK级别为-1: 确保信息数据发送成功,会发送多次

0.11 版本的 Kafka新特性: 幂等性。
所谓的幂等性就是指Producer 不论向 Server 发送多少次重复数据,Server 端都只会持久化一条。幂等性结合 At Least Once 语义,就构成了Kafka 的Exactly Once 语义

消费方式:

主要是拉和推两种模式:

推数据: 各个机器上的速率不一样,不容易出现协调,会出现消费者来不及处理的情况
拉数据: 根据自己的处理情况,拉取数据,但是这样的话,就要维护一个通信,来询问消息队列中是否有消息

消费者分区分配策略

RoundRobin: 这样的策略不太容易符合业务逻辑需求
在这里插入图片描述
Range: kafka 默认使用的,更容易符合业务逻辑

使用: 假设有主题T1,有0 1 2 一共3个分区, 一个消费者组,组中有消费者A和消费者B都订阅了T1, 会将0 1分配给A, 2 分配给B

在这里插入图片描述
也有可能会出现下面的情况:
在这里插入图片描述

注意: 当消费者添加或减少时,都会进行重新分配.

leader的选举和controller的作用:

controller:
1.Kafka 集群中有一个 broker 会被选举为 Controller,负责管理集群 broker 的上下线,所有 topic 的数据写入磁盘,分区副本分配和 leader 选举等工作。

2.Controller 的管理工作都是依赖于 Zookeeper 的。

3.其他节点会隔一段时间来看一下controller是否存在,如果不存在就自己成为controller

leader的选举:
在这里插入图片描述

kafka事务:

producer事务:

原因: 为了实现跨分区跨会话的事务,需要引入一个全局唯一的 Transaction ID,并将 Producer 获得的PID 和Transaction ID 绑定。这样当Producer 重启后就可以通过正在进行的Transaction ID 获得原来的PID。

Coordinator:
为了管理Transaction,Kafka 引入了一个新的组件Transaction Coordinator。Producer 就是通过和 Transaction Coordinator 交互获得 Transaction ID 对应的任务状态。Transaction Coordinator 还负责将事务所有写入 Kafka 的一个内部 Topic,这样即使整个服务重启,由于事务状态得到保存,进行中的事务状态可以得到恢复,从而继续进行。

注: 通过Transaction ID 和 PID绑定的方式,再使用幂等性, ack =-1 级别来真正的完成数据的重复性

consumer事务:

上述事务机制主要是从Producer 方面考虑,对于 Consumer 而言,事务的保证就会相对较弱,尤其时无法保证 Commit 的信息被精确消费。这是由于 Consumer 可以通过 offset 访问任意信息,而且不同的 Segment File 生命周期不同,同一事务的消息可能会出现重启后被删除的情况
比如:
在这里插入图片描述

消息发送的流程:

在这里插入图片描述
main线程: 将消息进行拦截器过滤, 序列化,进行分区信息,到RecordAccumulator(缓冲区)
RecordAccumulator: 相当于缓冲区,将信息和分区的信息先存储起来
sender线程: 将数据进行拉取到topic的分区当中


整理概述

最后再对前面的知识进行一个整理概述吧! 多谢各位大佬的观看,有错误的地方请指出来!
在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值