当前位置: 首页 > 科技观察

如何保证Kafka写入的数据在突然宕机的情况下不丢失?

时间:2023-03-18 12:14:45 科技观察

上周分享的一篇文章《Kafka如何实现每秒上百万的超高并发写入?》。相信大家都知道写入Kafka的数据会写入磁盘。这篇文章就讲讲如何保证写入Kafka的数据不丢失?暂且不考虑写入磁盘的具体过程。我们来看下图,它代表了Kafka的核心架构原理。Kafka分布式存储架构那么现在的问题是,如果每天产生几十TB的数据,是不是都写在一台机器的磁盘上了?这显然不靠谱!所以,这里不得不考虑数据格式存储的分布,下面结合Kafka的具体情况说说。在Kafka中,有一个核心概念叫做“Topic”。您可以将此Topic视为一个数据集合。例如,如果你现在有一个网站用户行为数据要写入Kafka,你可以创建一个名为“user_access_log_topic”的主题,将所有用户行为数据写入其中。那么,如果要将电商网站订单数据的增删改查记录写入Kafka,可以创建一个名为“order_tb_topic”的Topic,将订单表的所有变更记录写入其中。那我们举个例子来说说这个用户行为话题。每天几十TB的数据往里面写,你觉得放在一台机器上靠谱吗?显然不靠谱,所以Kafka有一个概念叫Partition,就是把一个Topic数据集拆分成多个数据分区。您可以将其视为多个数据片段。每个Partition可以在不同的机器上存储部分数据。这样一来,不是可以把一个大数据集分布存储在多台机器上吗?让我们看看下图,一起来体验一下。Kafka高可用架构但是这时候我们又会遇到一个问题,就是如果某台机器宕机了,这台机器上Partition管理的数据不会丢失吗?所以,我们要做更多的Copyredundancy,每个Partition都可以在另一台机器上有一个副本,这样如果一台机器宕机,只丢失一个Partition的副本。如果一个Partition有多个副本,Kafka会选举其中一个Parititon副本为Leader,其他Partition副本为Follower。只有LeaderPartition对外提供读写操作,FollowerPartition从LeaderPartition同步数据。一旦LeaderPartition宕机,其他FollowerPartition将被选举为新的LeaderPartition,对外提供读写服务。这不是实现了高可用架构吗?请看下图看流程:Kafka写入数据丢失问题下面我们来看一下,在什么情况下写入Kafka中的数据会丢失?其实也很简单。大家都知道,写入的数据是写入到一个Partition的Leader,然后那个Partition的Follower会从Leader同步数据。但是如果一个数据刚刚写入LeaderPartition,还没来得及同步到Follower,LeaderPartiton所在的机器突然死机了怎么办?请看下图:如上图所示,此时有一段数据还没有同步到Partition0,Follower上去了,然后Partition0的Leader所在的机器宕机了。这时候Partition0的Follower会被选举为新的Leader对外提供服务,那么用户就无法读取刚刚写入的数据了?因为Partition0的Follower还没有同步到最后一条数据。这时候就会造成数据丢失的问题。Kafka的ISR机制是什么?现在先把这个问题搁置一旁,不谈如何解决。我们再回顾一下Kafka的一个核心机制,就是ISR机制。简单来说,这个机制就是为每个Partition自动维护一个ISR列表。这个列表中肯定有一个Leader,那么它也会包含与Leader同步的Follower。也就是说,Leader的一个Follower只要和他保持数据同步,就会存在于ISR列表中。但是如果follower因为自身的一些问题不能及时从leader同步数据,那么这个follower就会被认为是“out-of-sync”,被踢出ISR列表。所以大家首先要明白这个ISR是什么。说白了就是Kafka自动维护和监控哪些Follower及时跟上Leader的数据同步。如何保证Kafka写入的数据不会丢失?所以如果想要保持写入Kafka的数据不丢失,需要保证以下几点:每个Partition在ISR列表中至少要有一个Follower来跟上Leader的数据同步。每次写入数据,要求至少有一个PartitionLeader写入成功,ISR中至少有一个Follower也写入成功,才算写入成功。如果不满足以上两个条件,写入就会一直失败,生产系统会不断尝试重试,直到满足以上两个条件,才可以认为写入成功。按照上面的思路配置相应的参数,保证写入Kafka的数据不会丢失。好的!下面我们来分析一下上面的需求。首先,ISR列表中必须至少有一个Follower。那是必要的。如果Leader没有Follower,或者Follower不能及时同步Leader的数据,那么这件事情肯定是办不下去的。第二,每次写入数据时,要求不仅Leader写入成功,ISR中至少有一个Follower也写入成功。看下面的图片。这个要求是为了保证每次写入数据时,Leader和Follower都必须写入成功才算写入成功。保证一条数据一定有两个以上的副本。这时候如果Leader宕机了,可以切换到那个Follower上,那么Follower上就有刚刚写入的数据,此时数据不会丢失。如上图,如果leader现在没有follower,或者只是写信给leader,leader会马上down,还没来得及同步给follower。在这种情况下,写入会失败,然后你会让生产者不断重试,直到Kafka恢复正常,满足以上条件再继续写入。这样写入kafka的数据就不会丢失。总结***综上所述,其实Kafka的数据丢失问题涉及方方面面。比如生产端的缓存问题,包括消费者端的问题,以及Kafka自身内部的底层算法和机制,也有可能造成数据丢失。但是写数据通常会遇到一个比较大的问题,就是Leader切换的时候可能会出现数据丢失的情况。所以这篇文章只是说说生产环境下这个问题的解决方法。