kafka的可靠性保证

一、kafka的存储机制
kafka通过topic来分主题存放数据 主题内又有分区 分区还可以有多个副本 ,分区的内部还细分为若干个segment。
所谓的分区 其实就是在 kafka对应存储目录下创建的文件夹,文件夹的名字是主题名加上分区编号 编号从0开始。
所谓的segment 其实就只在分区对应的文件夹下产生的文件。一个分区会被划分成大小相等的若干segment 这样一方面保证了分区的数据被划分到多个文件中保证不会产生体积过大的文件 另一方面可以基于这些segment文件进行历史数据的删除 提高效率。
一个segment又由 一个.log和一个.index文件组成,其中.log文件为数据文件用来存放数据分段数据 .index为索引文件保存对对应的.log文件的索引信息。这两个文件的命名规则为:partition全局的第一个segment从0开始,后续每个segment文件名为上一个segment文件最后一条消息的offset值,数值大小为64位,20位数字字符长度,没有数字用0填充。
而在.index文件中 保存了对对应 .log文件的索引信息,通过查找.index文件可以获知每个存储在当前segment中的offset在.log文件中的开始位置 而每条日志 有其固定格式 保存了 包括offset编号 日志长度 key的长度 等相关信息 通过这个固定格式中的数据可以确定出当前offset的结束位置 从而对数据进行读取
真正开始读取指定分区中 某个offset对应的数据时 先根据offset和当前分区 的所有segment的名称做比较 确定出数据在哪个segment中 查找该segment的索引文件 确定当前offset在数据文件中的开始位置 从该位置开始读取数据文件 在根据数据格式判断结果 最终 获取到完整数据。




二、消费者消费数据时的可靠性保证
在Kafka中维护了 一个AR列表 包括所有的分区的副本
AR又分为ISR和OSR
只有ISR内的副本都同步了leader中的数据,该数据才能被提交,才能被消费者访问
OSR内的副本是否同步了leader的数据,不影响数据的提交,OSR内的follower 尽力的去同步leader,可能数据版本或落后
AR = ISR + OSR
最开始所有的副本都在ISR中 在kafka工作的过程中 如果某个副本同步速度慢于replica.lag.time.max.ms指定的阈值,则被踢出ISR 存入OSR  如果后续速度恢复可以回到ISR中

LEO - LogEndOffset - 分区的最新的数据的offset
HW - HighWatermark - 只有写入的数据被 同步到 所有的ISR中的 副本后,数据才认为已提交,HW更新到该位置,HW之前的数据才可以被消费者访问,保证 没有 同步完成的数据不会被消费者 访问到
在leader宕机后,只能从ISR列表中选取新的leader,无论ISR中哪个副本被选为 新的leader都知道HW之前的数据,可以保证在切换了leader后,消费者可以继续看到 之前已经 提交的数据


**AR ISR OSR LEO HW  这些信息都被保存在Zookeeper中 


三、生产者生产数据的可靠性
生产者向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接受 数据则数据重复了



四、HW截断机制 
如果leader宕机 选出了新的leader 而新的leader并没有完全同步之前leader的所有数据,之后接受了后续新的数据,此时旧的leader恢复,则会发现新的leader中的数据和自己持有的数据不一致,此时旧的leader会将自己的数据阶段到之前宕机之前的hw位置,之后同步新leader的数据


如果ISR中的follower同步了leader中的部分数据,之后leader宕机,follower也宕机,此时选出新的leader可能同步了部分之前 leader的数据,之后接受新的数据,此时follower恢复过来,发现 自己持有的 数据和新 的leader的数据不一致,此时阶段数据到 之前的 hw将,然后和 新的leader同步 数据


五、leader选举
当leader宕机时 会选择ISR中的一个follower成为新的leader


如果ISR中的所有副本都宕机 怎么办 


unclean.leader.election.enable=false
策略1:必须等待ISR列表中的副本活过来才选择其成为leader继续工作
unclean.leader.election.enable=true
策略2:选择任何一个活过来的副本 - 可能不在ISR中 - 成为leader继续工作


策略1,可靠性有保证,但是可用性低,只有最后挂了leader活过来kafka才能恢复
策略2,可用性高,可靠性没有保证,任何一个副本活过来就可以继续工作,但是有可能存在数据不一致的情况



六、kafka可靠性的保证
At most once: 消息可能会丢,但绝不会重复传输
At least once:消息绝不会丢,但可能会重复传输
Exactly once:每条消息肯定会被传输一次且仅传输一次

**kafka最多保证At least once,可以保证不丢 但是可能会重复,为了解决重复需要引入唯一标识和去重机制,kafka提供了GUID实现了唯一标识,但是并没有提供自带的去重机制,需要开发人员基于业务规则自己去重.


七、分布式系统中的不可能三角 - CPA定义


Consistency:一致性
分布式环境下 任意时间点中 数据是否一致
Availability:可用性
分布式环境下 任意节点 是否具有完整的功能
Partition Tolerance:分区容忍性
是否可以采用分布式模式 容忍多态机器 一起工作 




CPA定义
在分布式系统开发中,以上三个特性,最多可以满足两个,同时满足以上三个特性的分布式系统是不可能的.








猜你喜欢

转载自blog.csdn.net/xiaoyutongxue6/article/details/80071973