[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bAk1dhqF-1635778465190)(2021-10-25-14-00-42.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tUW2RhHZ-1635778465194)(2021-10-25-14-07-21.png)]
采取了分片和索引机制
, 将每个partition对应的log数据文件分为多个segment,每个segment对应着两个文件–.index文件 + .log文件
, 另外每个.log 的文件是在config/server.properties中log.segment.bytes
规定了的, 通常是1GB.看下图, 这是一个topic分区文件夹中的几个分片, 可以看到每个分片的.log和.index的命名相同, 都是以当前分片的最小偏移量命名的.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g5td1Sny-1635778465977)(2021-10-25-14-13-52.png)]
index文件和log文件内的数据详解
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jeEToM9D-1635778465979)(2021-10-25-16-01-17.png)]
.index文件存储大量的索引信息, .log文件存储大量的数据, 索引文件中的元数据指向数据文件中消息的物理存储偏移地址.
kafka定位消息数据位置的步骤:
- 首先需要知道offset, 通过二分查找法, 找到存有这个offset信息的.index文件,
- 然后读取.log文件, 找到目标offset对应的消息数据在.log物理存储的偏移量(因为每条消息的存储大小都是固定的), 根据偏移量我们可以迅速定位到目标数据.
我们需要将producer发送的数据封装成一个ProducerRecord对象.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZXB5vtSh-1635778465197)(2021-10-26-09-04-45.png)]
随机整数值%topic可用的partition总数
, 取余结果就是partition值, 这种是常说的round-robin算法.Q:待解决问题: key是什么玩意?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a6WQ0eoM-1635778465200)(2021-11-01-14-57-02.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sDrGlrVd-1635778465203)(2021-10-26-09-17-27.png)]
follower与leader数据同步的策略(副本同步策略)
方案 | 优点 | 缺点 |
---|---|---|
1.半数以上完成同步, 就发送ack | 延迟低 | 选举新的leader时, 容忍n台结点的故障, 需要设置2n+1个副本 |
2. 全部完成同步,才发送ack | 选举新的leader时, 容忍n台节点的故障, 只需要设置n+1个副本 | 延迟高 |
kafka选择了第2种策略, 原因是:
1, 同样是为了容忍n台节点的故障, 半数同步的方案需要2n+1个副本, 而Kafka的每个分区都有大量的数据, 毫无疑问这种方案会造成大量数据的冗余.
2, 虽然全部同步完成的方案延迟较高, 但是网络延迟对Kafka 的影响较小.
Q: 没看懂半数跟全同步需要副本数量的问题?
A:
设置2n+1个副本数(注意是设置, 不是要求一定要有这些副本)
才能确保集群正常选举, 为啥呢? 可别忘了这2n+1采用这种了半数以上的同步机制, 这就使得在这些副本中肯定会有至少n+1个副本是正常的(这一点是必须能保证的), 这样才能可以正常恢复n+1个节点,正常选举出leader.设置n+1个副本数
才能确保集群能够正常选举, 这n+1个节点因为采用了全同步策略(这一点也是保证了最低n+1个节点正常同步出副本), 所以就能够确保集群中还有n+1个主机能够正常的选举出leader.补充:
- 半数存活机制;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Upf2w643-1635778465981)(2021-10-26-09-36-14.png)]
- 两种策略需要设置的副本数为什么会有不同呢?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4GLiVOnM-1635778465983)(2021-10-26-09-47-05.png)]
Leader维护了一个动态的ISR(in-sync replica set), 意为
和leader保持同步的follower集合
.
- 当ISR中的follower完成数据的同步之后, leader就会给follower发送ack.
- 如果follower长时间未向leader同步数据, 则该follower就会被踢出ISR, 该事件阈值由
replica.lag.time.max.ms
参数设定- Leader发生故障之后, 就会从ISR中选举新的leader.
acks 参数配置:
[acks = 0]:
broker发生故障时,有可能会丢失数据
.[acks =1 ]
在follower同步成功之前leader故障, 那么将会丢失数据
.[acks =-1 ]
在follower同步完成后, broker发送ack之前,leader发生故障, 将会从剩下的follower中重新选举新的leader, 然后producer会重新向新的leader发送数据, 由于此前数据已经同步过了, 此时就会造成数据的重复.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GfxFS1tP-1635778465204)(2021-10-26-11-04-43.png)]
LEO
(log end offset):每个副本最大的Offset偏移量, 标识当前.log文件(数据文件, 别自己混乱了)下一条待写入消息的offset偏移量.
HW
(high watermark):消费者能够见到的最大的Offset(即消费者只能拉取到这个偏移量前面的消息), 它是IRO队列中最小的LEO.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZsuDvx7K-1635778465206)(2021-10-26-11-26-12.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3asGfRBD-1635778465207)(2021-10-26-11-52-54.png)]
参考资料: 1. LEO和HW, 及其更新流程
Follower故障
Leader故障
At least once, 可以保证数据不丢失, 但是不能保证数据不重复, 相对的, 对于一些比较重要信息, 比如说交易数据, 下游数据消费者要求数据既不重复也不丢失, 即 Exactly Once语义. 在0.11之前的kafka只能保证数据不丢失, 然后在下游消费者处对数据做全局去重. 对于多个下游应用的情况, 每个都需要单独做全局去重, 无疑对性能有巨大的影响.
幂等性就是指Producer无论向Server发送多少次重复数据, Server端都只会持久化一条
, 幂等性结合At Least Once 语义, 就构成了Kafka的Exactly Once 语义, 即
如何启用Kafka 的幂等性呢?
要启用幂等性, 只需要将Producer的参数中
enable.idompotence
设置为true即可.
幂等性的实现原理和特点?
kafka 的consumer 采用pull(拉)模式从broker中拉取数据.
一个consumer group中有多个consumer, 一个topic有多个partition, 所以必然会涉及到partition的分配问题, 及确定哪个partition由哪个consumer来消费.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nE5vVOuV-1635778465209)(2021-10-28-22-18-37.png)]
RoundRobinAssignor(轮询)
, RangeAssignor
和 StickyAssignor
Kafka提供了消费者客户端参数
partition.assignment.strategy
来设置消费与订阅主题之间的分区分配策略.
默认情况下, 此参数的值为org.apache.kafka.clients.consumer.RangeAssignor
, 即采用RangeAssignor分配策略.
除此之外, Kafka还提供了另外两种分配策略, RoundRobinAssignor 和 StickyAssignor.
消费者客户端参数partition.assignment.strategy
可以配置多个分配策略, 彼此之间以逗号分隔.
[具体的分配策略]
n=分区数/消费者数量, m=分区数%消费者, 那么前m个消费者每个分配n+1个分区, 后面的(消费者数量-m)个消费者每个分配还是n个分区
.[举个栗子]
eg1. 假设消费者组有2个消费者c0, c1, 它俩订阅了2个主题t0,t1, 这俩topic每个主题都有四个分区, 分别是t0p1, t0p2, t0p3, t0p4 和 t1p1, t1p2, t1p3, t1p4.
eg2. 要是不均匀分配呢? 假设2个消费者c0, c1, 订阅了2个主题t0, t1, 每个主题都只有3个分区, 分别是为: t0p0, t0p1, t0p2, 和 t1p0, t1p1, t1p2.
上面例子没看懂, 看看下面这张图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nDLxuMhd-1635778465984)(2021-10-28-20-44-46.png)]
可以看到, 使用RangeAssignor分配策略的话, 会出分配不均匀的现象, 如果将类似的情形扩大, 则有可能出现部分消费者过载的情况.
partition.assignment.strategy
参数值为org.apache.kafka.clients.consumer.RoundRobinAssignor
[举个栗子]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N6X0u2MX-1635778465210)(2021-10-28-20-54-49.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SRcSz4jc-1635778465213)(2021-10-28-20-56-42.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hcrzhmcU-1635778465216)(2021-10-28-21-25-02.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ImdrlVUq-1635778465218)(2021-10-28-21-26-34.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YqzAhwvy-1635778465219)(2021-10-28-21-33-18.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hro0SJdO-1635778465221)(2021-10-28-21-33-52.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1J0QuzmI-1635778465223)(2021-11-01-17-40-55.png)]
0.9版本kafka之前 Offset的存储(位于zk中), 即上面灰色框图的内容, 在0.9版本之后, 由于offset存储在kafka集群的topic中, 所以灰色框图也就不复存在啦.
消费者组消费一个topic 的过程(拿bigdata02消费bigdata01往topic offsetTest生产的消息为例)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bv4hdiVn-1635778465228)(2021-11-01-21-09-22.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e6VJXvYp-1635778465230)(2021-11-01-21-10-28.png)]
'/consumers/topic/newBD/console-consumer-对应消费者组id/newBD/offsets'
, 可以看到, newBD有两个分区0号,1号, 因为我们还没消费, 所以查看0号分区的值为0.[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lS0GMHpn-1635778465232)(2021-11-01-21-16-01.png)]
…如此循环往复. offset不断递增.
why so?
现在只有一个主题bigdata, 两个分区, 0和1号,
- 生产的时候没有指定分区号和key,就是轮询着往里生产数据(这里用到生产者的消息分配策略)
- 然后消费的时候, 因为是1个主题2个分区, 1个消费者 ,所以消费数据也是轮询的(其实是RangeAssignor退化为了RoundRobinAssignor), 先去0号分区消费一条数据, 此时zk的消费者组–bigdata主题–0号分区的 offset为1, 然后又消费了一条数据, 注意此时消费的应该是这一主题下1号分区下的一条数据(轮询嘛, 雨露均沾), 所以zk的 消费者组–bigdata主题–1号分区-- offset为1, 依次往复下去. (这里用到消费者的消息分配策略)
Kafka集群采用了分布式存储和处理
顺序读写
零拷贝技术
费一条数据, 此时zk的消费者组–bigdata主题–0号分区的 offset为1, 然后又消费了一条数据, 注意此时消费的应该是这一主题下1号分区下的一条数据(轮询嘛, 雨露均沾), 所以zk的 消费者组–bigdata主题–1号分区-- offset为1, 依次往复下去. (这里用到消费者的消息分配策略)
Kafka集群采用了分布式存储和处理
顺序读写
零拷贝技术