深入了解Kafka架构之数据可靠性保证

为保证 producer 发送的数据,能可靠的发送到指定的 topic,topic 的每个 partition 收到producer 发送的数据后,都需要向 producer 发送 ack(acknowledgement 确认收到),如果producer 收到 ack,就会进行下一轮的发送,否则重新发送数据。

1、ack应答机制

Kafka 为用户提供了三种可靠性级别,用户可根据对可靠性和延迟的要求进行权衡。

  1. 0
    producer 不等待 broker 的 ack,这一操作提供了一个最低的延迟,broker 一接收到还没有写入磁盘就已经返回,当broker 故障时有可能丢失数据.

  2. 1
    producer 等待 broker 的 ack,partition 的 leader 写入磁盘成功后返回 ack,如果在 follower同步成功之前 leader 故障,那么将会丢失数据;

  3. (-1) all
    producer 等待 broker 的 ack,partition 的 leader 和 follower 全部写入磁盘成功后才返回 ack。但是如果在 follower 同步完成后,broker 发送 ack 之前,leader 发生故障,那么会造成数据重复。极限条件下还有可能会造成数据丢失,即ISR数据集中只有leader一个的情况下,其他follower因为落后于消费进度的时间长度(replica.lag.time.max)而被踢出ISR,这时leader写入磁盘后返回ack,然后突然宕机,这种情况会造成数据丢失。

上述的副本描述的都是在ISR数据集中的

2、Exactly Once

  1. At Least Once
    将服务器的 ACK 级别设置为-1,可以保证 Producer 到 Server 之间不会丢失数据,即 At Least Once语义。

  2. At Most Once
    将服务器 ACK 级别设置为 0,可以保证生产者每条消息只会被发送一次,即 At Most Once 语义。

At Least Once 可以保证数据不丢失,但是不能保证数据不重复;相对的,At Most Once可以保证数据不重复,但是不能保证数据不丢失。但是对于一些非常重要的信息,要求数据既不重复也不丢失,即 Exactly Once 语义。0.11 版本以前的 Kafka,对此是无能为力的,只能保证数据不丢失,在下游消费者对数据做全局去重。对于多个下游应用的情况,每个都需要单独做全局去重,这就对性能造成了很大影响。0.11 版本的 Kafka,引入了一项重大特性:幂等性。

  1. 幂等性
    所谓的幂等性就是指 Producer 不论向 Server 发送多少次重复数据,Server 端都只会持久化一条。幂等性结合 At Least Once 语义,就构成了 Kafka 的 Exactly Once 语义。即:At Least Once + 幂等性 = Exactly Once。要启用幂等性,只需要将 Producer 的参数中 enable.idompotence 设置为 true 即可。

Kafka的幂等性实现其实就是将原来下游需要做的去重放在了数据上游。开启幂等性的 Producer 在初始化的时候会被分配一个 PID,发往同一 Partition 的消息会附带 Sequence Number。而Broker 端会对<PID, Partition, SeqNumber>做缓存,当具有相同主键的消息提交时,Broker 只会持久化一条。

如果Producer重启,那么 PID 就会变化,所以幂等性无法保证跨会话的 Exactly Once;当Producer向不同的分区发送消息时,恰好在发送数据到最后一个分区的时候Producer宕机了,当Producer重启后,PID已经变化,因而仍然需要向broker发送数据,会造成数据不一致情况,所以幂等性也无法保证跨分区的 Exactly Once。它只能保证单分区,单会话下的Exactly Once。

3、Producer 事务

由上面我们可以知道幂等性无法保证跨分区跨会话的 Exactly Once。Kafka从 0.11 版本开始引入了事务支持。事务可以保证 Kafka 在 Exactly Once 语义的基础上,生产和消费可以跨分区和会话,要么全部成功,要么全部失败。

为了实现跨分区跨会话的事务,需要引入一个全局唯一的 Transaction ID,并将 Producer获得的PID 和Transaction ID 绑定。这样当Producer 重启后就可以通过正在进行的 TransactionID 获得原来的 PID。为了管理 Transaction,Kafka 引入了一个新的组件 Transaction Coordinator。Producer 就是通过和Transaction Coordinator 交互获得 Transaction ID 对应的任务状态。TransactionCoordinator 还负责将事务所有写入 Kafka 的一个内部 Topic,这样即使整个服务重启,由于事务状态得到保存,进行中的事务状态可以得到恢复,从而继续进行。

猜你喜欢

转载自blog.csdn.net/qq_42599616/article/details/107216573