简单理解 Kafka 的消息可靠性策略

发表于 3年以前  | 总阅读数:725 次

背景

部门的开发同学最近在开发一个活动的过程中,需要关注大量的应用后台逻辑,捕捉各种事件的触发。在设计时打算采用 kafka 消息队列进行业务逻辑的解耦,这样活动开发和后台开发同学的工作就分离开了。但是使用的同学不是很熟悉其原理,担心以下几个问题:

  • 我什么业务场景下使用消息队列
  • 我发消息的时候,需要等 ack 嘛?
  • 我发了消息之后,消费者一定会收到嘛?
  • 申请腾讯云的 kafka 实例后,各种参数怎么设置呀?
  • 遇到各种故障时,我的消息会不会丢?
  • 消费者侧会收到多条消息嘛?消费者 svr 重启后消息会丢失嘛?

这些问题都很正常,在开始接触和使用时总会有这样或那样的问题。一般情况下,不做了解,使用各种默认的推荐值,也是可以 work 的。但是我们要优雅的提升自己的姿(知)势(识)。学习其背后的原理,至少在遇到一般的问题时,能够分析和处理问题,做到心中有数。

什么时候使用消息队列?

简单来说,3 个关键词, 异步/消峰/解耦,可以理解为:

  • 我做完了后面的我不管了
  • 工作太多了,先放一放我慢慢处理
  • 怎么产生的我不管/怎么处理我不管

以下图为例:

用户提交评论中, 写入数据库后,存在需要捕捉评论事件的多个逻辑步骤。如果在接口处理过程中,顺序的处理不同的步骤,非常繁琐。我们可以批量的通知各个步骤(异步),无需返回直接处理当次的支付其他逻辑(解耦)。看起来就清爽多了,另外,消息队列也可以作为缓存暂存发出的消息,不再需要考虑调用各个步骤时时延逻辑的异常场景。

本文以讲解 kafka 中的可靠性设计为例,其它消息队列的选型暂不涉及。

Kafka 基本概念

在回答文章前面的问题之前,需要简单介绍一下各种概念。Kafka 从拓扑上分有如下角色:

  • Consumer: 消费者,一般以 API 形式存在于各个业务 svr 中
  • Producer: 生产者,一般以 API 形式存在于各个业务 svr 中
  • Kafka broker: kafka 集群中的服务器,topic 里的消息数据存在上面

Producer 采用发送 push 的方式将消息发到 broker 上,broker 存储后。由 consumer 采用 pull 模式订阅并消费消息。

如图所示,Kafka 从存储结构上,有如下角色:

  • Topic:kafka 处理的消息的逻辑大类集合,可以理解为表。写入不同的 topic 即写入不同的表。
  • Partition: Topic 下的物理分组,1 个 topic 可以分为多个 partition, 每个 partition 是一个有序的队列(大文件)。Partition 中每一条消息都有一个有序的 offset。
  • Msg: 消息,通信的基本单位。每个 msg 在 topic 下的不同 partiton 仅有一份,在 partition 中有一个唯一的 offset 用于定位。
  • Replica: 副本,partition 的数据冗余备份,用于实现分布式的数据可靠性,但引入了不同副本间的数据一致性问题,带来了一定的复杂度。
  • Leader/follower: replica 的角色,leader replica 用来提供该 partition 的读写服务。Follower 不停的从 leader 侧同步写入的消息。它们之间的消息状态采用一致性策略来解决。

Kakfa 的存储格式

为了方便后文更好的理解 broker 上的消息状态一致性策略,需要简单介绍一下消息的存储格式。当 Producer 发送一条消息到 broker 中, 会根据分配 partition 规则选择被存储到哪一个 partition, 如果 partition 规则设置的合理,消息会均匀的分布到不同的 partition 里,这样就实现了水平扩展。

Pruducer 可以认为 partition 是一个大的串行文件,msg 存储时被分配一个唯一的 offset。Offset 是一个逻辑意义上的偏移,用于区分每一条消息。

而 partition 本身作为文件,可以有多个多个副本 replica(leader/follower)。多个 replica 分布在在不同的 broker 上。如果要回答如何在 broker 之间保证存储的消息和状态不会丢失,就要回答 broker 之间的各个 replica 的消息状态一致性如何解决,包括 producer 已经提交了哪些消息,哪些消息已经落地,哪些消息在节点故障后不会丢失。

异步发送时的消息可靠性保证

回到文章开头提到的几个问题,在使用 kafka 消息队列做异步发送时,如何保证消息的可靠性?如何回答开头的几个问题?这里要分为 3 个部分讲解可靠性保证。

生产者的可靠性保证

回答生产者的可靠性保证,即回答:

  1. 发消息之后有么有 ack
  2. 发消息收到 ack 后,是不是消息就不会丢失了

而 Kafka 通过配置来指定 producer 生产者在发送消息时的 ack 策略:

Request.required.acks=-1 (全量同步确认,强可靠性保证)
Request.required.acks = 1(leader 确认收到, 默认)
Request.required.acks = 0 (不确认,但是吞吐量大)

如果想实现 kafka 配置为 CP(Consistency & Partition tolerance) 系统, 配置需要如下:

request.required.acks=-1
min.insync.replicas = ${N/2 + 1}
unclean.leader.election.enable = false

如图所示,在 acks=-1 的情况下,新消息只有被 ISR 中的所有 follower(f1 和 f2, f3) 都从 leader 复制过去才会回 ack, ack 后,无论那种机器故障情况(全部或部分), 写入的 msg4,都不会丢失, 消息状态满足一致性 C 要求。 正常情况下,所有 follower 复制完成后,leader 回 producer ack。

异常情况下,如果当数据发送到 leader 后部分副本(f1 和 f2 同步), leader 挂了?此时任何 follower 都有可能变成新的 leader, producer 端会得到返回异常,producer 端会重新发送数据,但这样数据可能会重复(但不会丢失), 暂不考虑数据重复的情况。

min.insync.replicas 参数用于保证当前集群中处于正常同步状态的副本 follower 数量,当实际值小于配置值时,集群停止服务。如果配置为 N/2+1, 即多一半的数量,则在满足此条件下,通过算法保证强一致性。当不满足配置数时,牺牲可用性即停服。

异常情况下,leader 挂掉,此时需要重新从 follower 选举 leader。可以为 f2 或者 f3。

如果选举 f3 为新 leader, 则可能会发生消息截断,因为 f3 还未同步 msg4 的数据。Kafka 的通 unclean.leader.election.enable 来控制在这种情况下,是否可以选举 f3 为 leader。旧版本中默认为 true,在某个版本下已默认为 false,避免这种情况下消息截断的出现。

通过 ack 和 min.insync.replicas 和 unclean.leader.election.enable 的配合,保证在 kafka 配置为 CP 系统时,要么不工作,要么得到 ack 后,消息不会丢失且消息状态一致。

min.insync.replicas 参数默认值为 1,即满足高可用性,只要有 1 台能工作即可。但此时可工作的 broker 状态不一定正确(可以想象为啥)

如果想实现 kafka 配置为 AP(Availability & Partition tolerance)系统:

request.required.acks=1
min.insync.replicas = 1
unclean.leader.election.enable = false

当配置为 acks=1 时,即 leader 接收消息后回 ack,这时会出现消息丢失的问题:如果 leader 接受到了 第 4 条消息,此时还没有同步到 follower 中,leader 机器挂了,其中一个 follower 被选为 leader, 则 第 4 条消息丢失了。当然这个也需要 unclean.leader.election.enable 参数配置为 false 来配合。但是 leader 回 ack 的情况下,follower 未同步的概率会大大提升。

通过 producer 策略的配置和 kafka 集群通用参数的配置,可以针对自己的业务系统特点来进行合理的参数配置,在通讯性能和消息可靠性下寻得某种平衡。

Broker 的可靠性保证

消息通过 producer 发送到 broker 之后,还会遇到很多问题:

  • Partition leader 写入成功, follower 什么时候同步?
  • Leader 写入成功,消费者什么时候能读到这条消息?
  • Leader 写入成功后,leader 重启,重启后消息状态还正常嘛?
  • Leader 重启,如何选举新的 leader?

这些问题集中在, 消息落到 broker 后,集群通过何种机制来保证不同副本建的消息状态一致性。

Kafka 消息备份和同步

Kafka 通过分区的多副本策略来解决消息的备份问题。通过 HW 和 LEO 的标识,来对应 ISR 和 OSR 的概念,用于类比共识性算法解决数据同步一致性的问题。

分区多副本即前文提到的 Partition 的 replica(副本) 分布在跟 partition 不相同的机器上, 通过数据冗余保证故障自动转移。而不同副本的状态形成了 ISR 和 OSR 的概念。

  • ISR : leader 副本保持一定同步的 follower 副本, 包括 leader 副本自己,叫 In Sync Replica
  • AR: 所有副本 (replicas) 统称为 assigned replicas, 即 AR
  • OSR: follower 同 leader 同步数据有一些延迟的节点

ISR 是 kafka 的同步策略中独有的概念,区别于 raft 等共识性算法。Raft 要求集群中要求 N/2+1 台正常,其在这种条件下通过复杂的算法保证选举出的新 leader 符合一致性状态。而 kafka 的 ISR 同步策略,通过 ISR 列表的可伸缩性和 HW&LEO 更新,一定程度上解决了消息一致性和吞吐性能之间的平衡。

ISR 通过 HW 和 LEO 的概念表示消息的同步状态:

  • HW: Highwater, 俗称高水位,它表示了一个特定的消息偏移量(offset), 在一个 parttion 中 consumer 只能拉取这个 offset 之前的消息(此 offset 跟 consumer offset 不是一个概念) ;
  • LEO: LogEndOffset, 日志末端偏移量, 用来表示当前日志文件中下一条写入消息的 offset;
  • leader HW: 该 Partititon 所有副本的 LEO 最小值;
  • follower HW: min(follower 自身 LEO 和 leader HW);
  • Leader HW = 所有副本 LEO 最小值;
  • Follower HW = min(follower 自身 LEO 和 leader HW)。

Leader 不仅保存了自己的 HW &LEO 还保存了远端副本的 HW &LEO

简单来说,每个副本都有 HW 和 LEO 的存储,而 leader 不但保存自己的 HW 和 LEO, 还保存了每个远端副本的 LEO。用于在自身的 HW 更新时计算值。可以看出由于 LEO 远端存储的特性,其实会导致副本真实的 LEO 和 leader 存储的 LEO 有短暂的数值差异,者会带来一些问题,后面再讲。

HW 和 LEO 的更新策略如下:

一次完整的写请求的 HW / LEO 更新流程:

1. 初始状态

Leader 所有的 HW&LEO 都为 0, follower 与 leader 建立连接,follower fetch leader, follower 所有 HW&LEO 都为 0

2. Follower 第一次 fetch:

Producer 发来一条消息到 leader, 此时 leader 的 LEO=1, follower 带着自己的 HW&LEO(都为 0) 开始 fetch, leader 的 HW=min(all follower LEO)=0, leader 记录 follower 的 LEO=0;follower 拉取到一条消息,带着消息和 leader 的 HW(0)&LEO(1)返回自身更新自己的 LEO=1, 更新自己的 HW=min(follower 自身 LEO(1) 和 leader HW(0))=0

3. Follower 第二次 fetch:

Follower 带着自己的 HW(0)&LEO(1) 去请求 leader .此时 leader 的 HW 更新为 1,leader 保存的 follower 的 LEO 更新为 1,带着 leader 的 HW(1)&LEO(1)返回自身,更新自己的 HW&LEO

此时回到刚才提到的问题,这种 HW 和 LEO 更新策略有个很明显的问题,即 follower 的 HW 更新需要 follower 的 2 轮 fetch 中的 leader 返回才能更新, 而 Leader 的 HW 已更新。这之间,如果 follower 和 leader 的节点发生故障,则 follower 的 HW 和 leader 的 HW 会处于不一致状态,带来比较多的一致性问题。比如如下场景:

  • Leader 更新完分区 HW 后,follower HW 还未更新,此时 follower 重启
  • Follower 重启后,LEO 设置为之前的 follower HW 值(0), 此时发生消息截断(临时状态)
  • Follower 重新同步 leader, 此时 leader 宕机,则不选举则不可用
  • Follower 被选举为 leader, 则 msg 1 永久丢失了

在 kafka 配置为 AP 系统的情况下,由于 min.insync.replicas 为 1, 这种重启后 follower 发生截断发生的概率会大大提升, 而在多个副本存在的情况下,情况可能还会更加糟糕。而 kafka 新版本为了解决这个 HW&LEO 的同步机制更新缺陷,引入了 Epoch 的概念。

Leader epoch 分两部分组成:

  • Epoch : 版本号。每当副本领导权发生变更时,都会增加该版本号。小版本号的 Leader 被认为是过期 Leader,不能再行使 Leader 权力。
  • 起始位移(Start Offset)。Leader 副本在该 Epoch 值上写入的首条消息的位移。

Leader epoch(1, 120) 说明这个 leader 的版本号为 1,版本的起始位置是 第 120 条消息开始的。Kafka Broker 会在内存中为每个分区都缓存 Leader Epoch 数据,同时它还会定期地将这些信息持久化到一个 checkpoint 文件中。当 Leader 副本写入消息到磁盘时,Broker 会尝试更新这部分缓存。如果该 Leader 是首次写入消息,那么 Broker 会向缓存中增加一个 Leader Epoch 条目,否则就不做更新。这样,每次有 Leader 变更时,新的 Leader 副本会查询这部分缓存,取出对应的 Leader Epoch 的起始位移,以避免数据丢失和不一致的情况。

示图如下:

Kafka 通过 ISR 的同步机制及优化策略,用 HW & LEO 的方式很好的确保了数据不丢失以及吞吐率。而 ISR 的管理最终都会反馈到 Zookeeper 上,其实现和 leader 的选举策略不再赘述。

Consumer 的可靠性策略

Consumer 的可靠性策略集中在 consumer 的投递语义上,即:

  • 何时消费,消费到什么?
  • 按消费是否会丢?
  • 消费是否会重复?

这些语义场景,可以通过 kafka 消费者的而部分参数进行配置,简单来说有以下 3 中场景:

1. AutoCommit(at most once, commit 后挂,实际会丢)

enable.auto.commit = true

auto.commit.interval.ms

配置如上的 consumer 收到消息就返回正确给 brocker, 但是如果业务逻辑没有走完中断了,实际上这个消息没有消费成功。这种场景适用于可靠性要求不高的业务。其中 auto.commit.interval.ms 代表了自动提交的间隔。比如设置为 1s 提交 1 次,那么在 1s 内的故障重启,会从当前消费 offset 进行重新消费时,1s 内未提交但是已经消费的 msg, 会被重新消费到。

2. 手动 Commit(at least once, commit 前挂,就会重复, 重启还会丢)

enable.auto.commit = false

配置为手动提交的场景下,业务开发者需要在消费消息到消息业务逻辑处理整个流程完成后进行手动提交。如果在流程未处理结束时发生重启,则之前消费到未提交的消息会重新消费到,即消息显然会投递多次。此处应用与业务逻辑明显实现了幂等的场景下使用。

特别应关注到在 golang 中 sarama 库的几个参数的配置:

sarama.offset.initial (oldest, newest)
offsets.retention.minutes

intitial = oldest 代表消费可以访问到的 topic 里的最早的消息,大于 commit 的位置,但是小于 HW。同时也受到 broker 上消息保留时间的影响和位移保留时间的影响。不能保证一定能消费到 topic 起始位置的消息。

如果设置为 newest 则代表访问 commit 位置的下一条消息。如果发生 consumer 重启且 autocommit 没有设置为 false, 则之前的消息会发生丢失,再也消费不到了。在业务环境特别不稳定或非持久化 consumer 实例的场景下,应特别注意。

一般情况下, offsets.retention.minutes 为 1440s。

3. Exactly once, 很难,需要 msg 持久化和 commit 是原子的

消息投递且仅投递一次的语义是很难实现的。首先要消费消息并且提交保证不会重复投递,其次提交前要完成整体的业务逻辑关于消息的处理。在 kafka 本身没有提供此场景语义接口的情况下,这几乎是不可能有效实现的。一般的解决方案,也是进行原子性的消息存储,业务逻辑异步慢慢的从存储中取出消息进行处理。

本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/T6gCc8OBgyV-yeAg_MUzPQ

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237231次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8065次阅读
 目录