Kafka如何保证消息的可靠性?

2022年9月26日08:17:38

Kafka分布式,高可用存储架构

总所周知,Kafka是一个分布式的、可分区的、可复制的消息系统。
也就是说一个topic中的消息是放在多个partition上的,可是当一台机器宕机后不就会导致部分消息不可消费吗?所以Kafka还做了多副本冗余,每个Partition都可以搞一个副本放在别的机器上,这样某台机器宕机,只不过是Partition其中一个副本丢失。

如果某个Partition有多副本的话,Kafka会选举其中一个Parititon副本作为Leader,然后其他的Partition副本是Follower。

只有Leader Partition是对外提供读写操作的,Follower Partition就是从Leader Partition同步数据。

一旦Leader Partition宕机了,就会选举其他的Follower Partition作为新的Leader Partition对外提供读写服务,这就实现了高可用架构。
Kafka如何保证消息的可靠性?

Kafka写入数据丢失问题

什么情况会导致Kafka中写入数据会丢失呢?

大家都知道写入数据都是往某个Partition的Leader写入的,然后那个Partition的Follower会从Leader同步数据,但是这个同步过程是异步的。也就是说如果此时1条数据刚写入Leader Partition1,还没来得及同步给Follower,Leader Partiton1所在机器突然就宕机了的话,此时就会选举Partition1的Follower作为新的Leader对外提供服务,然后用户就读不到刚才写入的那条数据了。因为Partition0的Follower上是没有同步到最新的一条数据的,这个时候就会造成数据丢失的问题。
Kafka如何保证消息的可靠性?

Kafka的ISR机制

这个机制简单来说,就是会自动给每个Partition维护一个ISR列表,这个列表里一定会有Leader,然后还会包含跟Leader保持同步的Follower。

也就是说,只要Leader的某个Follower一直跟他保持数据同步,那么就会存在于ISR列表里。

但是如果Follower因为自身发生一些问题,导致不能及时的从Leader同步数据过去,那么这个Follower就会被认为是“out-of-sync”,从ISR列表里移除。

怎么保证Kafka写入的数据不丢失

  1. 每个Partition都至少得有1个Follower在ISR列表里,跟上了Leader的数据同步
  2. 每次写入数据的时候,都要求至少写入Partition Leader成功,同时还有至少一个ISR里的Follower也写入成功,才算这个写入是成功了

如果不满足上述两个条件,那就一直写入失败,让生产系统不停的尝试重试,直到满足上述两个条件,然后才能认为写入成功

这个时候万一leader宕机,就可以切换到那个follower上去,那么Follower上是有刚写入的数据的,此时数据就不会丢失了。

关于第二点就需要去配置相应ack参数,才能保证写入Kafka的数据不会丢失。

ack参数

acks参数,是在Kafka Producer,也就是生产者里设置的。

这个参数实际上有三种常见的值可以设置,分别是:0、1 和 all。

  • ack = 0,意思就是我的Kafka Producer在客户端,只要把消息发送出去,不管那条数据有没有在哪怕Partition Leader上落到磁盘,直接就认为这个消息发送成功了。

  • ack = 1,意思就是说只要Partition Leader接收到消息而且写入本地磁盘了,就认为成功了,不管他其他的Follower有没有同步过去这条消息了。这种设置是kafka默认的设置

  • ack = all,意思就是说,Partition Leader接收到消息之后,还必须要求ISR列表里跟Leader保持同步的那些Follower都要把消息同步过去,才能认为这条消息是写入成功了。

采用这种设置,如果Partition Leader刚接收到了消息,但是结果Follower没有收到消息,此时Leader宕机了,那么客户端会感知到这个消息没发送成功,他会重试再次发送消息过去。

此时可能Partition 2的Follower变成Leader了,此时ISR列表里只有最新的这个Follower转变成的Leader了,那么只要这个新的Leader接收消息就算成功了。这样就可以大概率保证发送端发送的消息不会丢失。

消费端

唯一可能导致消费者弄丢数据的情况:就是说,你已经消费到了这个消息,然后消费者那边自动提交了 offset,让 Kafka 以为你已经消费好了这个消息,但其实你才刚准备处理这个消息,但是还没处理,消费端就挂了,此时这条消息就丢了。

解决方案:
关闭自动提交 offset,在处理完之后自己手动提交 offset,就可以保证数据不会丢。但是此时确实还是可能会有重复消费,比如你刚处理完,还没提交 offset,结果自己挂了,此时肯定会重复消费一次,自己保证幂等性就好了。

  • 作者:红丶
  • 原文链接:https://blog.csdn.net/weixin_42494845/article/details/111366145
    更新时间:2022年9月26日08:17:38 ,共 2021 字。