Kafka怎么保证数据的一致性和可靠性?

1、可靠性的保证?
下面通过从topic的分区副本、producer发送到broker、leader选举三个方面来阐述kafka的可靠性。

<1>、Topic的分区副本
其实在kafka-0.8.0之前的版本是还没有副本这个概念的,在之后版本引入了副本这个架构,每个分区设置几个副本,可以在设置主题的时候可以通过replication-factor参数来设置,也可以在broker级别中设置defalut.replication-factor来指定,一般我们都设置为3;
三个副本中有一个副本是leader,两个副本是follower,leader负责消息的读写,follower负责定期从leader中复制最新的消息,保证follower和leader的消息一致性,当leader宕机后,会从follower中选举出新的leader负责读写消息,通过分区副本的架构,虽然引入了数据冗余,但是保证了kafka的高可靠。
Kafka的分区多副本是Kafka可靠性的核心保证,把消息写入到多个副本可以使Kafka在崩溃时保证消息的持久性及可靠性。

<2>、Producer发送消息到broker
topic的每个分区内的事件都是有序的,但是各个分区间的事件不是有序的,producer发送消息到broker时通过acks参数来确认消息是否发送成功,request.required.acks参数有三个值来代表不同的含义;
acks=0:表示只要producer通过网络传输将消息发送给broker,那么就会认为消息已经成功写入Kafka;但是如果网卡故障或者发送的对象不能序列化就会错误;
acks=1:表示发送消息的消息leader已经接收并写入到分区数据文件中,就会返回成功或者错误的响应,如果这时候leader发生选举,生产者会再次发送消息直到新的leader接收并写入分区文件;但是这种方式还是可能发生数据丢失,当follower还没来得及从leader中复制最新的消息,leader就宕机了,那么这时候就会造成数据丢失;
acks=-1:代表leader和follower都已经成功写入消息是才会返回确认的响应,但是这种方式效率最低,因为要等到当前消息已经被leader和follower都写入返回响应才能继续下条消息的发送;
所以根据不用的业务场景,设置不同的acks值,当然producer发送消息有两种方式:同步和异步,异步的方式虽然能增加消息发送的性能,但是会增加数据丢失风险,所以为了保证数据的可靠性,需要将发送方式设置为同步(sync)。

<3>、Leader选举
在每个分区的leader都会维护一个ISR列表,ISR里面就是follower在broker的编号,只有跟得上leader的follower副本才能加入到ISR列表,只有这个列表里面的follower才能被选举为leader,所以在leader挂了的时候,并且unclean.leader.election.enable=false(关闭不完全的leader选举)的情况下,会从ISR列表中选取第一个follower作为新的leader,来保证消息的高可靠性。

综上所述,要保证kafka消息的可靠性,至少需要配置一下参数:
topic级别:replication-factor>=3;
producer级别:acks=-1;同时发送模式设置producer.type=sync;
broker级别:关闭不完全的leader选举,即unclean.leader.election.enable=false;

2、数据一致性?
这里说的一致性指的是不管是老的leader还是新的leader,consumer都能读到一样的数据。
Kafka怎么保证数据的一致性和可靠性?_第1张图片
假设分区副本为3,副本0位leader,副本1和2位follower,在ISR列表里面副本0已经写入了message4,但是consumer只能读取message2,这是因为所有副本都同步了message2,只有High water mark以上的message才能被consumer读取,而High water mark取决于ISR列表里偏移量最小的分区,对应上图中的副本2;
所以在message还没有被follower同步完成时会被认为是"不安全的",如果consumer读取了副本0中的message4,这时候leader挂了,选举了副本1为新的leader,别的消费者去消费的时候就没有message4,就会造成不同的consumer消费的数据不一致,破坏了数据的一致性。
在引入了High water mark机制后,会导致broker之间的消息复制因为某些原因变慢,消息到达消费者的时间也会延长(需要等消息复制完了才能消费),延迟的时间可以通过参数来设置:replica.lag.time.max.ms(它指定了副本在复制消息时可被允许的最大延迟时间)

你可能感兴趣的:(Kafka)