Kafka如何保证数据可靠性
1、可靠性策略
为保证 producer
发送的数据,能可靠的发送到指定的 topic
,topic
的每个partition
收producer
发送的数据后,都需要向producer
发送ack确认收到,如果
producer
收到ack
,就会进行下一轮的发送,否则重新发送数据。
2、同步策略的问题
-
Partition
到底什么时候发送这个ack
?确保有
follower
与leader
同步完成,leader
再发送ack
,这样才能保证leader
挂掉之后,能在follower
中选举出新的leader
。 -
多少
follower
与leader
同步完成我们才发送ack
?- 半数以上
- 全部
现在我们就第二个问题,也就是副本同步策略,做以简单评估。
解决方案 | 优点 | 缺点 |
---|---|---|
半数以上follower 同步完成后发送ack | 效率高,低延迟 | 若leader 宕机,选举新leader 时,如果考虑到N 台机器故障,我们需要2N+1 个副本 |
全部follwer 同步完成后发送ack | 若leader 宕机,选举新leader 时,如果考虑到N 台机器故障,我们只需要N+1 个副本 | 延迟高 |
TIPS:关于上述优缺点的简单解释。
- 半数以上方案的缺点解释:宕机的N个机器,它们可能是同步好数据的那部分,也可能是没有同步好的那部分。如果坏掉的是同步好的那部分,那我们只需要N+1个副本(多出来的这个副本是仅仅或者说专门用来备份的节点机器,懂我意思吧),如果坏掉的不是同步好的那部分,本身没有同步的数据,而且还缺一份备份,所以需要2N+1
- 全部同步才发送
ack
的方案:因为是所有的follower
都同步好了,参照上面的解释,我们就仅仅需要N+1个副本就好。
Kaffka最后选择了哪种方案作为同步策略呢?
Kafka选择了第二种全部同步完成后再发送ack的策略。
- 第一种方案会造成大量数据冗余
- 第二种方案虽然可能延迟高,但是这种延迟对于Kafka来说影响其实不大。
3、ISR (in-sync replica set 和leader保持同步的follow集合)
在我们采用第二种全部同步完成后再发送ack
的策略后,会出现一个新问题。
生产者发送消息,leader
接收数据,所有的follower
开始同步数据,但是其中某一个follower
可能因为某种故障,迟迟无法同步完成,基于第二种策略来思考,leader
就会一直等下去直到这个follower
完成同步才能发送ack
。设想如果故障的follower
同步一分钟、一小时、一天、一年才完成呢?leader
要一直等下去吗?
为了解决这样一个问题,Kafka有这样一个策略。
Leader
其实会维护一个动态的in-sync replica set
(ISR),即和leader
保持同步的follower
集合。如果某个follower
长时间没有向leader
同步数据,则该follower
踢出ISR,其中这个同步时间可由replica.lag.time.max.ms
参数来设定。
🐕TIPS:leader挂了就是从ISR中重新选举的。
4、ACK应答机制
在实际环境中,数据有重要和不重要这样一个区别。对于不重要的数据,可以容忍有少量数据丢失的情况下,其实没有必要等ISR中全部同步成功的。
基于此,Kafka为用户提供了三种可靠级别,我们就可以根据实际可靠性和延迟的要求进行权衡。
我们可以通过设置acks
参数来选择,下面简单介绍acks
参数的配置:
0
:producer
不等待broker
的ack
,可想而知,这样做延迟会是最低的,broker
一接收到就返回,不管你是否已经写入磁盘做好备份等数据可靠性的操作,那么当broker
故障时就有可能数据丢失。1
:producer
等待broker
的ack
,partition
的leader
写盘成功后返回ack
,如果在follower
同步成功之前leader
故障,那么将会丢失数据。-1/all
:producer
等待broker
的ack
,partition
的leader
和follower
全部落盘成功后才返回ack
。但是如果在follower
同步完成后,broker
发送ack
之前,leader
发生故障,那么会造成数据重复。