Kfaka学习

整体框架图整理

在这里插入图片描述

基本概念

术语

Topic
Kafka将消息分门别类,每一类的消息称之为一个主题(Topic)。一般都是一个业务一个topic

Producer
发布消息的对象称之为主题生产者(Kafka topic producer)

Consumer
订阅消息并处理发布的消息的对象称之为主题消费者(consumers)

Broker
已发布的消息保存在一组服务器中,称之为Kafka集群。集群中的每一个服务器都是一个代理(Broker)。 消费者可以订阅一个或多个主题(topic),并从Broker拉数据,从而消费这些已发布的消息。

partition
分区,一个topic可能有多个分区,分区是队列的,因此其中的message就有了偏移量offset来标识位置

Replica
副本 即防止数据丢失的冗余副本 分为领导者副本和追随者副本(leader和follower),follower唯一价值就是当leader的候补,当leader挂掉,选举新的leader。

核心逻辑:
生产者发消息给kafka服务器
消费者从kafka读取消息
kafka服务器依托zookeeper进行服务协调管理

应用场景

消息传输,解耦生产者消费者

保存用户操作消息,需要巨大吞吐量

对多路消息实时收集 ,做日后统计

日志的收集汇总方案

磁盘写入

  kafka会将所有数据持久化到磁盘,但kfaka只是把数据写入到操作系统的页缓存中,然后由
  操作系统来决定什么时候把页缓存的数据写回到磁盘。写入页缓存的速度非常快。

消息简述

  Topic - partition - message三级结构
  Topic:Kafka将消息分门别类,每一类的消息称之为一个主题(Topic)。一般都是一个业务一个topic
  Topic —一对多> partition —一对多> message
  每个partition都是一个队列,因此每个消息都有一个偏移值offset来标识位置

主要对象

生产者

1.构造 一个Properties对象
2.根据properties构建Producer对象
3.指定发送的topic和消息内容
4.send方法发送消息
5.关闭生产者

是线程安全的 可以在多个线程中使用同一个Producer实例

消费者

1.构造一个Properties对象,指明属于的groupId
2.根据Properties构造Consumer
3.调用方法订阅topic
4.循环获取消息
5.处理获取到的消息
6.consumer对象关闭

消费者组 group
消费者实例 consumer

topic的每个消息可以发送到多个订阅它的group中,但每个group中只有一个consumer接收到这个消息

消费者位移(offset)
每个consumer会为它消费的分区维护自己的位置信息来记录当前消费信息的位置

多线程
一般两个线程 用户主线程 后台心跳线程
主要的任务全都在用户主线程中执行,因此并不是线程安全的

分区分配(重平衡)
当消费者组成员变动,比如加入consumer实例;消费者组订阅topic变动;订阅topic分区数发生变更。触发分区分配。
分配策略:
1 . 按consumer数将分区按块划分:consumer1:topic1,topic2,topic3这种
2 . 轮询consumer挨个划分:consumer1 :topic1,topic4,topic7这种
3 . sticky策略

多线程实现consumer
在这里插入图片描述
允许实现独立consumer,建立consumer与分区之间的直接联系而不通过销售组的分配

设计原理

Producer设计

生产者->服务器 消息体:ProducerRecord
– Topic :该消息所属的topic
– PartitionID : 该消息所属的分区
– Key:消息key
– Value:消息体
– timestamp:消息时间戳

服务器->生产者 消息体 :RecordMetadata
Offset:消息在分区日志中的位移消息
topicPartition:所属topic的分区
timestamp:时间戳
checksum:消息 CRC32 码 。
serializedKeySize:序列化后的key字节数
serializedValueSize:序列化后的value字节数

发送流程
是完全的异步流程:
在这里插入图片描述
kafkaProducer的Send方法流程

1.序列化+计算目标分区
  序列化数据并填充部分数据,发送实现类处理

2.写入消息缓冲池
  默认32MB的缓冲 send区 保存待发送的消息

3.sender线程预处理及消息发送
  不断轮询缓冲区寻找已做好发送准备的分区
  将轮询获得的各个batch按照目标分区所在的leader broker进行分组
  将分组后的batch通过底层创建的Socket连接发送给各个broker
  等待服务器端发送response回来
在这里插入图片描述
4.sender线程处理response
   一旦Sender线程接收到response将依次(按照消息发送顺序)调用batch中的回调方法

Broker端设计

基本功能与流程

  kafka的集群管理是依赖zookeeper实现的 此处称为broker,是介乎于生产者和消费者之间的角色 ,负责消息的持久化工作

  每个broker会将自己注册为zookeeper下的一个临时节点
当broker崩溃,就会触发zookeeper删除临时节点,从而触发broker崩溃流程

  数据在broker端的持久化其实就是日志
  保证系统高可用就是有副本日志,有leader日志和follower日志,只读取leader的日志

  ISR:每个topic中维护的,一定与leader日志数据同步过的follower副本列表

ISR中的位移信息:
  起始位移:当前副本所含第一条消息的位移
  高水印值:HW,该副本最新一条已提交消息位移,leader上,超过HW的消息都是“未提交成功的”
  日志末端位移:LEO,该副本下一条待写入消息的位移

broker请求处理的全流程
在这里插入图片描述
在这里插入图片描述

kafka精髓:brokerController

多个broker组成kafka集群

需要一个controller来进行集中控制和维护
在这里插入图片描述

一、选举Leader和ISR

  控制器从ZK的/brokers/topics加载一个topic所有分区的所有副本,从分区副本列表中选出一个作为该分区的leader,并将该分区对应所有副本置于ISR列表,其他分区类似;其他topic的所有分区也类似。

二、同步元数据信息包括broker和分区的元数据信息

  控制器将ZK的/brokers/ids以及上一个步骤得到的topic下各分区leader和ISR将这些元数据信息同步到集群每个broker。
并且当有broker或者分区发生变更时及时更新到集群保证集群每一台broker缓存的是最新元数据。

三、broker增删监听与处理
3.1 broker加入的监听和处理

  控制器启动时就起一个监视器监视ZK/brokers/ids/子节点。当存在broker启动加入集群后都会在ZK/brokers/ids/增加一个子节点brokerId,控制器的监视器发现这种变化后,控制器开始执行broker加入的相关流程并更新元数据信息到集群。

3.2 broker崩溃的监听与处理

  控制器启动时就起一个监视器监视ZK/brokers/ids/子节点。当一个broker崩溃时,该broker与ZK的会话失效导致ZK会删除该子节点,控制器的监视器发现这种变化后,控制器开始执行broker删除的相关流程并更新元数据信息到集群。

四 topic变化监听与处理
4.1 topic创建的监听与处理

  控制器启动时就起一个监视器监视ZK/brokers/topics/子节点。当通过脚本或者请求创建一个topic后,该topic对应的所有分区及其副本都会写入该目录下的一个子节点。控制器的监视器发现这种变化后,控制器开始执行topic创建的相关流程包括leader选举和ISR并同步元数据信息到集群;且新增一个监视器监视ZK/brokers/topics/<新增topic子节点内容>防止该topic内容变化。

4.2 topic删除的监听与处理

  控制器启动时就起一个监视器监视ZK/admin/delete_topics/子节点。当通过脚本或者请求删除一个topic后,该topic会写入该目录下的一个子节点。控制器的监视器发现这种变化后,控制器开始执行topic删除的相关流程包括通知该topic所有分区的所有副本停止运行;通知所有分区所有副本删除数据;删除ZK/admin/delete_topics/<待删除topic子节点>。

五、分区变化监听与变化处理
5.1 分区重分配监听与处理

  分区重分配通过KAFKA管理员脚本执行完成一个topic下分区的副本重新分配broker。

  控制器启动时就起一个监视器监视ZK/admin/reassign_part/子节点。当通过脚本执行分区重分配后会在该目录增加一个子节点,子节点内容是按照一定格式构建的重分配方案,控制器的监视器发现这种变化后,控制器开始执行分区重分配相关流程如同步元数据信息。

5.2 分区扩展监听与处理

  如上面4.1 所述当创建一个topic后,控制器会增加一个监视器监视ZK/brokers/topics/<新增topic子节点内容>防止该topic内容变化。当通过脚本执行分扩展后会在该目录增加新的分区目录。控制器的监视器发现这种变化后,控制器开始执行分区扩展相应流程如选举leader和ISR并同步。

PS:其实这里的分配是partition在broker上的分配
1.将所有Broker(假设共n个Broker)和待分配的Partition排序
2.将第i个Partition分配到第(i mod n)个Broker上 (这个就是leader)
3.将第i个Partition的第j个Replica分配到第((i + j) mode n)个Broker上

consumer端设计

Consumer Group 的五个状态:
1.Empty:Group 没有任何成员;
2.PreparingRebalance:Group 正在准备进行 Rebalance;
3.AwaitingSync:Group 正在等待来 group leader 发送分区分配方案;
4.Stable:稳定的状态,正常消费;
5.Dead:Group 内已被废弃,不相应任何请求。

  首次创建 ① ->新成员加入② ,同时会等待一段时间让更多成员加入 ->成员加入到时后/所有成员都加入③->分配方案确定后 进入④

  ⑤状态需要首先④状态,然后所有成员离组->②->① 元数据过期后 ->⑤

新概念: consumerLeader和coordinator
consumerLeader:consumer group的Leader ,一般是第一个加入consumer group的consumer。
coordinator:broker端的设计,负责consumer group的组管理

组管理(这里是哪个consumer读取哪个partition的分配)
1.加入consumer group组 :
  请求为joinGroup。每个入组的consumer要给coordinator发送自身数据。coordinator选择一个为 leader consumer(第一个入组),发送所有consumer成员的元数据信息。其它consumer会收到一个空数组。

2.leader consumer拿到数据,按照分区策略进行分区,分配规则按照 分区分配(重平衡)设计的来分配(在 对象 - 消费者)

  每个consumer都会给coordinator发送SyncGroup请求,但只有leader consumer的请求包含分配方案。coordinator会解析方案,将每个consumer对应的分区封装进每个consumer的response中。每个consumer只会获得自己的分区信息。

通信协议

clients端处理通信的逻辑:
在这里插入图片描述
broker端处理通信的逻辑:
在这里插入图片描述
  broker端会创建一个请求阻塞队列,专门接收来自于client端的请求。同时也会有多个线程创建来处理请求。

日志存储

  类似于关系型数据库的记录,以分区为单位,日志信息会被写入该topic的该分区
  对于某个日志而言,有日志段文件+索引文件

精确一次语义

  最多一次语义(At least once semantics):只处理一次,但消息可能会被丢失
  至少一次语义(At most once semantics):消息不会丢失,但可能会多次处理
  精确一次语义(Exactly once semantics):消息会被处理切只处理一次

producer端 EOS(精确一次) 实现

  实现幂等性:即无论该操作重复多少次,结果都一样
  每个producer都有一个相应的PID,发送消息有分区号 每个PID+分区号 都有一个对应的序列号(PID,分区号) ->序列号
  如果该序列号小于或等于当前broker中保存的序列号,不做处理
  不支持多个producer同时实现EOS

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值