Kafka剖析

Kafka剖析

1、总体概述
2、生产者流程:4步,2线程
3、消费者流程:5步,消费组与消费者,分区策略
4、broker之基本概念:
controller、topic、partition、replica,leader replica、follower replica、AR=ISR+OSR,HW与LEO
5、broker之日志存储格式
6、broker之日志索引
7、broker之日志清理,log.cleanup.policy=delete,compact,墓碑消息
8、零拷贝技术
9、延时任务之时间轮

总结:
1、生产者分区分配+消费者订阅主题的分区分配+创建主题broker中分区分配;
2、controller的选举+leader副本的选举;

===================================================
图1:

图2:
生产者流程
4步:
  1、配置生产者客户端参数及创建相应的生产者实例
  2、构建待发送的消息
  3、发送消息
  4、关闭生产者实例

主线程:拦截器 → 序列化器 →分区器 → 记录累加器
sender线程:
  状态转换:
    <分区, Deque<ProducerBatch>> →
    <Node, List<ProducerBatch> →
    <Node,Request>
  InFlightRequests
  元数据更新:leastLoadedNode

图3
leastLoadedNode产生

===================================================
图4:
消费者流程
5步:
  1、配置消费者客户端参数及创建相应的消费者实例
  2、订阅主题
  3、拉取消息并消费
  4、提交消费位移,自动、手动
图5:
消费端offset提交的是position
  5、控制或关闭消费

分区策略:RangeAssignor,RoundRobinAssignor ,StickyAssignor

===================================================
一个集群只有一个控制器;
控制器是干嘛的?
  监听broker、主题、分区相关的变化
  更新集群元数据
  启动并管理分区状态机和副本状态机

一个分区由一个leader副本,一个集群由n个leader副本;
一个分区的副本=leader副本+follower副本
topic和partition都是逻辑上的,topic-partition才是实际存在的目录;
AR=ISR+OSR,HW与LEO

图6:
基本概念理解及副本同步

===================================================
图7:
kafka日志存储结构及日志格式
日志索引
先找LogSegment→ 再从索引文件中找索引项(二分法)→ 从索引项对应的物理位置顺序读取数据。

图8:
跳跃表
日志索引—找LogSegment用的跳跃表。
LogSegment大小?1G
索引文件大小?10M与实际大小
LogSegment的切分条件

日志删除:delete
基于时间、基于日志大小、基于日志起始偏移量(logStartOffset)

添加到deleteableSegments → 从跳表中移除 → “.deleted” → 由延迟任务来删除

图9:
基于时间

日志清理:compact
清理线程 → 根据污浊率选择要清理的分区 →对分区中的LogSegment分组 →找可清理部分→SkimpyOffsetMap→清理到期的墓碑消息→更新cleaner checkpoint

图10:
日志清理
图11:
日志清理-分组

===================================================
图12:

DMA就是主板上一个实际的芯片
DMA就好比一个中间代理者角色

图13:
普通拷贝/非零拷贝
图14:
零拷贝
kafka哪些场景使用了零拷贝技术?

时间轮与层级时间轮
图15:
在这里插入图片描述
DelayQueue → SystemTimer→TimerTaskList、TimerTask
DelayQueue的时间复杂度是 O ( n l o g ( n ) ) O(nlog(n))
DelayQueue中的元素要指定一个到期时间
DelayQueue里面的元素是什么?
为什么kafka中的定时器时间复杂度是 O ( 1 ) O(1)

例1:
如果我们有1千万个TimerTask,最小时间单位是ms,最大一个任务要300年后执行
第1层:
  tickMs=1ms,interval= 2 0 1 20^1 =20ms
第2层:
  tickMs=20ms,interval= 2 0 2 20^2 =400ms
第3层:
  tickMs=400ms,interval= 2 0 3 20^3 =8000ms=8s
第4层:
  tickMs=8000ms,interval= 2 0 4 20^4 =160000ms=160s
第5层:
  tickMs=160000ms,interval= 2 0 5 20^5 =3200000ms=53m
第6层:
  tickMs=3200000ms,interval= 2 0 6 20^6 =160000ms=18h
第10层:
  interval= 2 0 10 20^{10} =160000ms=324年

降级?
例子:
当currentTime=16:29:07:0400时,第1个时间轮走了20圈,第2个时间轮走了1圈,第3个时间轮才走1个区间,指针指向1位置(最开始是指向0位置)

此时对于第3层第2个桶(即第2个TimerTaskList)中的TimerTask就到期了,那么会从DelayQueue中poll出队头,即第2个TimerTaskList,对第2个TimerTaskList里面的TimerTask进行重新add。这次add他们俩会被添加到第2层时间轮中,这就是时间轮的降级

什么时候指针更新?任何一层,只要有TimerTaskList到期就触发更新
if TimerTaskList的到期时间 >= currentTime + tickMs:
currentTime = timeMs - (timeMs % tickMs)

图16:

猜你喜欢

转载自blog.csdn.net/weixin_38052918/article/details/107414933