kafka 通过 topic 来分主题存放数据,主题内有分区,分区可以有多个副本,分区的内部还细分为若干个 segment。
所谓的分区其实就是在 kafka 对应存储目录下创建的文件夹,文件夹的名字是主题名加上分区编号,编号从 0 开始。
kafka全套视频学习资料:http://www.atguigu.com/download.shtml
1、segment
所谓的 segment 其实就是在分区对应的文件夹下产生的文件。
一个分区会被划分成大小相等的若干 segment,这样一方面保证了分区的数据被划分到多个文件中保证不会产生体积过大的文件;另一方面可以基于这些 segment 文件进行历史数据的删除,提高效率。
一个 segment 又由一个.log 和一个.index 文件组成。
1..log
.log 文件为数据文件用来存放数据分段数据。
2..index
.index 为索引文件保存对对应的.log 文件的索引信息。
在.index 文件中,保存了对对应.log 文件的索引信息,通过查找.index 文件可以获知每个存储在当前 segment 中的 offset 在.log 文件中的开始位置,而每条日志有其固定格式,保存了包括 offset 编号、日志长度、key 的长度等相关信息,通过这个固定格式中的数据可以确定出当前 offset 的结束位置,从而对数据进行读取。
3.命名规则
这两个文件的命名规则为:
partition 全局的第一个 segment 从 0 开始,后续每个 segment 文件名为上一个 segment 文件最后一条消息的 offset 值,数值大小为 64 位,20 位数字字符长度,没有数字用 0 填充。
2、读取数据
开始读取指定分区中某个 offset 对应的数据时,先根据 offset 和当前分区的所有 segment 的名称做比较,确定出数据在哪个 segment 中,再查找该 segment 的索引文件,确定当前 offset 在数据文件中的开始位置,最后从该位置开始读取数据文件,在根据数据格式判断结果,获取完整数据。
二、可靠性保证
1、AR
在 Kafka 中维护了一个 AR 列表,包括所有的分区的副本。AR 又分为 ISR 和 OSR。
AR = ISR + OSR。
AR、ISR、OSR、LEO、HW 这些信息都被保存在 Zookeeper 中。
1.ISR
ISR 中的副本都要同步 leader 中的数据,只有都同步完成了数据才认为是成功提交了,成功提交之后才能供外界访问。
在这个同步的过程中,数据即使已经写入也不能被外界访问,这个过程是通过 LEO-HW 机制来实现的。
2.OSR
OSR 内的副本是否同步了 leader 的数据,不影响数据的提交,OSR 内的 follower 尽力的去同步 leader,可能数据版本会落后。
最开始所有的副本都在 ISR 中,在 kafka 工作的过程中,如果某个副本同步速度慢于 replica.lag.time.max.ms 指定的阈值,则被踢出 ISR 存入 OSR,如果后续速度恢复可以回到 ISR 中。
3.LEO
LogEndOffset:分区的最新的数据的 offset,当数据写入 leader 后,LEO 就立即执行该最新数据。相当于最新数据标识位。
4.HW
HighWatermark:只有写入的数据被同步到所有的 ISR 中的副本后,数据才认为已提交,HW 更新到该位置,HW 之前的数据才可以被消费者访问,保证没有同步完成的数据不会被消费者访问到。相当于所有副本同步数据标识位。
在 leader 宕机后,只能从 ISR 列表中选取新的 leader,无论 ISR 中哪个副本被选为新的 leader,它都知道 HW 之前的数据,可以保证在切换了 leader 后,消费者可以继续看到 HW 之前已经提交的数据。
所以 LEO 代表已经写入的最新数据位置,而 HW 表示已经同步完成的数据,只有 HW 之前的数据才能被外界访问。
5.HW 截断机制
如果 leader 宕机,选出了新的 leader,而新的 leader 并不能保证已经完全同步了之前 leader 的所有数据,只能保证 HW 之前的数据是同步过的,此时所有的 follower 都要将数据截断到 HW 的位置,再和新的 leader 同步数据,来保证数据一致。
当宕机的 leader 恢复,发现新的 leader 中的数据和自己持有的数据不一致,此时宕机的 leader 会将自己的数据截断到宕机之前的 hw 位置,然后同步新 leader 的数据。宕机的 leader 活过来也像 follower 一样同步数据,来保证数据的一致性。
2、生产者可靠性级别
通过以上的讲解,已经可以保证 kafka 集群内部的可靠性,但是在生产者向 kafka 集群发送时,数据经过网络传输,也是不可靠的,可能因为网络延迟、闪断等原因造成数据的丢失。
kafka 为生产者提供了如下的三种可靠性级别,通过不同策略保证不同的可靠性保障。
其实此策略配置的就是 leader 将成功接收消息信息响应给客户端的时机。
通过 request.required.acks 参数配置:
1:生产者发送数据给 leader,leader 收到数据后发送成功信息,生产者收到后认为发送数据成功,如果一直收不到成功消息,则生产者认为发送数据失败会自动重发数据。
当 leader 宕机时,可能丢失数据。
0:生产者不停向 leader 发送数据,而不需要 leader 反馈成功消息。
这种模式效率最高,可靠性最低。可能在发送过程中丢失数据,也可能在 leader 宕机时丢失数据。
-1:生产者发送数据给 leader,leader 收到数据后要等到 ISR 列表中的所有副本都同步数据完成后,才向生产者发送成功消息,如果一只收不到成功消息,则认为发送数据失败会自动重发数据。
这种模式下可靠性很高,但是当 ISR 列表中只剩下 leader 时,当 leader 宕机让然有可能丢数据。
此时可以配置 min.insync.replicas 指定要求观察 ISR 中至少要有指定数量的副本,默认该值为 1,需要改为大于等于 2 的值
这样当生产者发送数据给 leader 但是发现 ISR 中只有 leader 自己时,会收到异常表明数据写入失败,此时无法写入数据,保证了数据绝对不丢。
虽然不丢但是可能会产生冗余数据,例如生产者发送数据给 leader,leader 同步数据给 ISR 中的 follower,同步到一半 leader 宕机,此时选出新的 leader,可能具有部分此次提交的数据,而生产者收到失败消息重发数据,新的 leader 接受数据则数据重复了。
3、leader 选举
当 leader 宕机时会选择 ISR 中的一个 follower 成为新的 leader,如果 ISR 中的所有副本都宕机,怎么办?
有如下配置可以解决此问题:
unclean.leader.election.enable=false
策略 1:必须等待 ISR 列表中的副本活过来才选择其成为 leader 继续工作。
unclean.leader.election.enable=true
策略 2:选择任何一个活过来的副本,成为 leader 继续工作,此 follower 可能不在 ISR 中。
策略 1,可靠性有保证,但是可用性低,只有最后挂了 leader 活过来 kafka 才能恢复。
策略 2,可用性高,可靠性没有保证,任何一个副本活过来就可以继续工作,但是有可能存在数据不一致的情况。
4、kafka 可靠性的保证
At most once:消息可能会丢,但绝不会重复传输。
At least once:消息绝不会丢,但可能会重复传输。
Exactly once:每条消息肯定会被传输一次且仅传输一次。
kafka 最多保证 At least once,可以保证不丢,但是可能会重复,为了解决重复需要引入唯一标识和去重机制,kafka 提供了 GUID 实现了唯一标识,但是并没有提供自带的去重机制,需要开发人员基于业务规则自己去重。
关键词:大数据培训
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。