kafka架构四之高可用

AR ISR OSR

分区中的所有副本统称为AR (Assigned Replicas)。

在Kafka 中备份日志文件被称为replica,replica 又分为leader replica 和follower replica,而follower replica存在的唯一目的就是防止消息丢失,并不参与具体的业务逻辑的交互。只有leader 才参与服务,follower的作用就是充当leader的候补,平时的操作也只有信息同步。ISR (in-sync replica)也就是这组与leader保持同步的replica集合,我们要保证不丢消息,首先要保证ISR的存活(至少有一个备份存活),并且消息提交成功。那存活的概念是什么呢,就是说不仅需要机器正常,还需要跟上leader的消息进度,当达到一定程度的时候就会认为“非存活”状态。

与leader 副本同步滞后过多的副本,不包括leader 副本, 组成OSR (Out-of-Sync Replicas),由此可见,AR = ISR + OSR。在正常情况下,所有的 follower 副本都应该与leader 副本保持一定程度的同步,即 AR=ISR,OSR集合为空。
ISR 与 HW和LEO也有紧密的关系,HW是Hight watermark 的缩写,俗称高水位,它标识了一个特定的消息偏移量offset。消费者只能拉取到这个offset 之前的消息。
下图代表一个日志文件,这个日志文件有9条消息,第一条消息的offset 为0,最后一条消息的offset 为8,日志文件的HW为6,表示消费者只能拉取到 offset 在0到5之间的消息。
在这里插入图片描述
下面通过一个简单的示例来进行说明 ISR集合,以及HW和LEO的关系
在这里插入图片描述
在消息写入leader 副本后,follower 副本会发起拉取请求来拉取消息3和消息4 以进行消息同步。
在这里插入图片描述
在同步过程中,不同的follower 副本的同步效率也不尽相同,如图,在某一时刻 follwoer1 完全跟上了leader 副本,而 follower2 只同步了消息3,如此leader的LEO为5,follwoer1的LEO为5,follwoer2的LEO为4,那么分区的HW取最小值4,此时消费者可以消费0到3之间的消息。
在这里插入图片描述
所有的副本都成功写入消息3和消息4,整个分区的HW和LEO 都变为5,因此消费者可以消费到offset 为4的消息了。
在这里插入图片描述

Leader ElectionR

引入Replication之后,同一个Partition可能会有多个Replica,而这时需要在这些Replication之间选出一个Leader,Producer和Consumer只与这个Leader交互,其它Replica作为Follower从Leader中复制数据。

因为需要保证同一个Partition的多个Replica之间的数据一致性(其中一个宕机后其它Replica必须要能继续服务并且即不能造成数据重复也不能造成数据丢失)。如果没有一个Leader,所有Replica都可同时读/写数据,那就需要保证多个Replica之间互相(N×N条通路)同步数据,数据的一致性和有序性非常难保证,大大增加了Replication实现的复杂性,同时也增加了出现异常的几率。而引入Leader后,只有Leader负责数据读写,Follower只向Leader顺序Fetch数据(N条通路),系统更加简单且高效

Replica分配机制

为了更好的做负载均衡,Kafka尽量将所有的Partition均匀分配到整个集群上。一个典型的部署方式是一个Topic的Partition数量大于Broker的数量。同时为了提高Kafka的容错能力,也需要将同一个Partition的Replica尽量分散到不同的机器。实际上,如果所有的Replica都在同一个Broker上,那一旦该Broker宕机,该Partition的所有Replica都无法工作,也就达不到HA的效果。同时,如果某个Broker宕机了,需要保证它上面的负载可以被均匀的分配到其它幸存的所有Broker上。

Kafka分配Replica的算法如下:

1.将所有Broker(假设共n个Broker)和待分配的Partition排序

2.将第i个Partition分配到第(i mod n)个Broker上

3.将第i个Partition的第j个Replica分配到第((i + j) mode n)个Broker上

消息传递同步策略

Producer在发布消息到某个Partition时,先通过ZooKeeper找到该Partition的Leader,然后无论该Topic的Replication Factor为多少,Producer只将该消息发送到该Partition的Leader。Leader会将该消息写入其本地Log。每个Follower都从Leader pull数据。这种方式上,Follower存储的数据顺序与Leader保持一致。Follower在收到该消息并写入其Log后,向Leader发送ACK。一旦Leader收到了ISR中的所有Replica的ACK,该消息就被认为已经commit了,Leader将增加HW并且向Producer发送ACK。

为了提高性能,每个Follower在接收到数据后就立马向Leader发送ACK,而非等到数据写入Log中。因此,对于已经commit的消息,Kafka只能保证它被存于多个Replica的内存中,而不能保证它们被持久化到磁盘中,也就不能完全保证异常发生后该条消息一定能被Consumer消费。

Consumer读消息也是从Leader读取,只有被commit过的消息才会暴露给Consumer。
Kafka Replication的数据流如下图所示:
在这里插入图片描述

ACK前需要保证有多少个备份

对于Kafka而言,定义一个Broker是否“活着”包含两个条件:

  • 一是它必须维护与ZooKeeper的session(这个通过ZooKeeper的Heartbeat机制来实现)。
  • 二是Follower必须能够及时将Leader的消息复制过来,不能“落后太多”。
    Leader会跟踪与其保持同步的Replica列表,该列表称为ISR(即in-sync Replica)。如果一个Follower宕机,或者落后太多,Leader将把它从ISR中移除。这里所描述的“落后太多”指Follower复制的消息落后于Leader后的条数超过预定值(该值可在 K A F K A H O M E / c o n f i g / s e r v e r . p r o p e r t i e s 中 通 过 r e p l i c a . l a g . m a x . m e s s a g e s 配 置 , 其 默 认 值 是 4000 ) 或 者 F o l l o w e r 超 过 一 定 时 间 ( 该 值 可 在 KAFKA_HOME/config/server.properties中通过replica.lag.max.messages配置,其默认值是4000)或者Follower超过一定时间(该值可在 KAFKAHOME/config/server.propertiesreplica.lag.max.messages4000FollowerKAFKA_HOME/config/server.properties中通过replica.lag.time.max.ms来配置,其默认值是10000)未向Leader发送fetch请求。

Kafka的复制机制既不是完全的同步复制,也不是单纯的异步复制。事实上,完全同步复制要求所有能工作的Follower都复制完,这条消息才会被认为commit,这种复制方式极大的影响了吞吐率(高吞吐率是Kafka非常重要的一个特性)。而异步复制方式下,Follower异步的从Leader复制数据,数据只要被Leader写入log就被认为已经commit,这种情况下如果Follower都复制完都落后于Leader,而如果Leader突然宕机,则会丢失数据。而Kafka的这种使用ISR的方式则很好的均衡了确保数据不丢失以及吞吐率。Follower可以批量的从Leader复制数据,这样极大的提高复制性能(批量写磁盘),极大减少了Follower与Leader的差距。

需要说明的是,Kafka只解决fail/recover,不处理“Byzantine”(“拜占庭”)问题。一条消息只有被ISR里的所有Follower都从Leader复制过去才会被认为已提交。这样就避免了部分数据被写进了Leader,还没来得及被任何Follower复制就宕机了,而造成数据丢失(Consumer无法消费这些数据)。而对于Producer而言,它可以选择是否等待消息commit,这可以通过request.required.acks来设置。这种机制确保了只要ISR有一个或以上的Follower,一条被commit的消息就不会丢失。
kafka消息写入流程
在这里插入图片描述

  • producer先从zookeeper的 "/brokers/…/state"节点找到该partition的leader
  • producer将消息发送给该leader
  • leader将消息写入本地log
  • followers从leader pull消息。
  • followers写入本地log后向leader发送ACK
  • leader收到所有ISR中的replication的ACK后,增加HW(high watermark,最后commit 的offset)并向producer发送ACK

如何处理Replica恢复

  • ISR={A,B,C} Leader A commit m1
    在这里插入图片描述

  • A fails, B is new leader ISR={B,C}
    B commit m2, not m3
    在这里插入图片描述

  • B commit m4, m5
    在这里插入图片描述

  • A comes back, truncates to m1 and catch up finally ISR={A,B,C}
    在这里插入图片描述
    在这里插入图片描述

如何处理Replica全部宕机

  • 等待ISR中任一Replica恢复,并选它为Leader
    等待时间较长,降低可用性
    或ISR中的所有Replica都无法恢复或者数据丢失,则该Partition将永不可用

  • 选择第一个恢复的Replica为新的Leader,无论它是否在ISR中
    并未包含所有已被之前Leader Commit过的消息,因此会造成数据丢失
    可用性较高

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值