Kafka数据可靠性保证三板斧-ACK/ISR/HW

程序源代码

共 3353字,需浏览 7分钟

 ·

2020-07-17 02:16

点击上方蓝色字体,选择“设为星标

回复”资源“获取更多资源

5b67f3cfdb36b3b804c80965cc6eee4d.webp

b02958e25b567bf42c55cbb536169617.webp

大数据技术与架构点击右侧关注,大数据开发领域最强公众号!

8992a0722606ca5862dce0607e68353a.webp

暴走大数据点击右侧关注,暴走大数据!b2f2c21997796d7fc22a18390da7bcea.webp
为保证producer发送的数据,能可靠的发送到指定的topic,topic的每个partition收到producer发送的数据后,都需要向producer发送ack(acknowledgement确认收到),如果producer收到ack,就会进行下一轮的发送,否则重新发送数据。575bed70528436b1290bf342d9660e7a.webp1.副本数据同步策略9433d54a4a3654e3d0f3923c7697e685.webpKafka选择了第二种方案(全部完成同步,才发送ack),原因如下:
  • 同样为了容忍n台节点的故障,第一种方案需要2n+1个副本,而第二种方案只需要n+1个副本,而Kafka的每个分区都有大量的数据,第一种方案会造成大量数据的冗余。

  • 虽然第二种方案的网络延迟会比较高,但网络延迟对Kafka的影响较小。

2.ISR,AR采用第二种方案之后,设想以下情景:leader收到数据,所有follower都开始同步数据,但有一个follower,因为某种故障,迟迟不能与leader进行同步,那leader就要一直等下去,直到它完成同步,才能发送ack。这个问题怎么解决呢?
Leader维护了一个动态的in-sync replica set (ISR-同步副本列表),意为和leader保持同步的follower集合。当ISR中的follower完成数据的同步之后,leader就会给follower发送ack。如果follower长时间未向leader同步数据,则该follower将被踢出ISR,该时间阈值由replica.lag.time.max.ms参数设定。Leader发生故障之后,就会从ISR中选举新的leader。
  • ISR(In-Sync Replicas ):与leader保持同步的follower集合

  • AR(Assigned Replicas):分区的所有副本

ISR是由leader维护,follower从leader同步数据有一些延迟(包括延迟时间replica.lag.time.max.ms和延迟条数replica.lag.max.messages两个维度, 当前最新的版本0.10.x中只支持replica.lag.time.max.ms这个维度),任意一个超过阈值都会把follower剔除出ISR, 存入OSR(Outof-Sync Replicas)列表,新加入的follower也会先存放在OSR中。AR=ISR+OSR。3.ack应答机制对于某些不太重要的数据,对数据的可靠性要求不是很高,能够容忍数据的少量丢失,所以没必要等ISR中的follower全部接收成功。所以Kafka为用户提供了三种可靠性级别,用户根据对可靠性和延迟的要求进行权衡,选择以下的配置。acks参数配置:
  • 0:producer不等待broker的ack,这一操作提供了一个最低的延迟,broker一接收到还没有写入磁盘就已经返回,当broker故障时有可能丢失数据;

  • 1:producer等待broker的ack,partition的leader落盘成功后返回ack,如果在follower同步成功之前leader故障,而由于已经返回了ack,系统默认新选举的leader已经有了数据,从而不会进行失败重试,那么将会丢失数据

a3525a179d65210a62ddcfd56006c15d.webp
  • -1(all):producer等待broker的ack,partition的leader和follower全部落盘成功后才返回ack。但是如果在follower同步完成后,broker发送ack之前,leader发生故障,导致没有返回ack给Producer,由于失败重试机制,又会给新选举出来的leader发送数据,造成数据重复。

65eeafd8d0e9653bb8c862c0415d7d8e.webp4. HW,LEO,LSO,LW名词解释
f286bfdcf2334e8122dd6502d06c9297.webp上图表示一个日志文件,这个日志文件中只有9条消息,第一条消息的offset(LogStartOffset)为0,最后一条消息的offset为8,offset为9的消息使用虚线表示的,代表下一条待写入的消息。日志文件的 HW 为6,表示消费者只能拉取offset在 0 到 5 之间的消息,offset为6的消息对消费者而言是不可见的。
  • LEO(log end offset):标识当前日志文件中已写入消息的最后一条的下一条待写入的消息的offset。上图中offset为9的位置即为当前日志文件的 LEO,LEO 的大小相当于当前日志分区中最后一条消息的offset值加1.分区 ISR 集合中的每个副本都会维护自身的 LEO ,而 ISR 集合中最小的 LEO 即为分区的 HW,对消费者而言只能消费 HW 之前的消息。

  • HW(High Watermark):所有副本中最小的LEO, 一个分区中所有副本最小的offset,取一个partition对应的ISR中最小的LEO作为HW,consumer最多只能消费到HW所在的位置上一条信息。

  • 注意:HW/LEO这两个都是指已写入消息的最后一条的下一条的位置而不是指最后一条的位置。

  • LSO(Last Stable Offset): 对未完成的事务而言,LSO 的值等于事务中第一条消息的位置(firstUnstableOffset),对已完成的事务而言,它的值同 HW 相同

  • LW(Low Watermark): 低水位, 代表 AR(分区中的所有副本)集合中最小的 logStartOffset 值

注意: LogStartOffset不可以缩写为LSO,因为在Kafka中,LSO特指LogStableOffset

5.故障处理细节

0888531e0295d9d24a32ec849b5e1720.webp1.follower故障follower发生故障后会被临时踢出ISR,待该follower恢复后,follower会读取本地磁盘记录的上次的HW,并将log文件高于HW的部分截取掉,从HW开始向leader进行同步。等该follower的LEO大于等于该Partition的HW,即follower追上leader之后,就可以重新加入ISR了。
2.leader故障leader发生故障之后,会从ISR中选出一个新的leader,之后,为保证多个副本之间的数据一致性,其余的follower会先将各自的log文件高于HW的部分截掉,然后从新的leader同步数据。
注意:这只能保证副本之间的数据一致性,并不能保证数据不丢失或者不重复。
6.ISR 集合和 HW、LEO的关系下面具体分析一下 ISR 集合和 HW、LEO的关系。
假设某分区的 ISR 集合中有 3 个副本,即一个 leader 副本和 2 个 follower 副本,此时分区的 LEO 和 HW 都分别为 3 。消息3和消息4从生产者出发之后先被存入leader副本。933816f332a724caa8a8b97adf3e7b41.webp在消息被写入leader副本之后,follower副本会发送拉取请求来拉取消息3和消息4进行消息同步。
在同步过程中不同的副本同步的效率不尽相同,在某一时刻follower1完全跟上了leader副本而follower2只同步了消息3,如此leader副本的LEO为5,follower1的LEO为5,follower2的LEO 为4,那么当前分区的HW取最小值4,此时消费者可以消费到offset0至3之间的消息。3a57c7c50db8cab0204911e4453ef5c7.webp当所有副本都成功写入消息3和消息4之后,整个分区的HW和LEO都变为5,因此消费者可以消费到offset为4的消息了67d35dfd43596c343a1b838932169401.webp由此可见kafka的复制机制既不是完全的同步复制,也不是单纯的异步复制。事实上,同步复制要求所有能工作的follower副本都复制完,这条消息才会被确认已成功提交,这种复制方式极大的影响了性能。而在异步复制的方式下,follower副本异步的从leader副本中复制数据,数据只要被leader副本写入就会被认为已经成功提交。在这种情况下,如果follower副本都还没有复制完而落后于leader副本,然后leader副本宕机,则会造成数据丢失。kafka使用这种ISR的方式有效的权衡了数据可靠性和性能之间的关系。
欢迎点赞+收藏+转发朋友圈素质三连



文章不错?点个【在看】吧! ?

浏览 19
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报