赞
踩
1、producer到broker的消息不丢失:ack机制
acks 参数配置:
0: producer 不等待 broker(或者说是leader)的 ack,这一操作提供了一个最低的延迟, broker 一接收到还没有写入磁盘的数据就已经返回,当 broker 故障时有可能丢失数据。可以保证数据不重复,但是不能保证数据不丢失。
1: producer 等待 broker 的 ack, partition 的 leader 落盘成功后返回 ack,如果在 follower同步成功之前 leader 故障,那么将会丢失数据;
-1(all) : producer 等待 broker 的 ack, partition 的 leader 和 ISR(同步副本) 里的follower 全部落盘成功后才返回 ack。但是如果在 follower 同步完成后, broker 发送 ack 之前, leader 发生故障,那么会造成数据重复。(假如ISR中没有follower,就变成了 ack=1 的情况)。可以保证数据不丢失,但是不能保证数据不重复。
2、broker到consumer消息不丢失:
consumer 采用 pull(拉) 模式从 broker 中读取数据。consumer会维护一个offset,该offset实时记录着自己消费的位置。同时消费者能见到的最大的 offset,是HW, 是ISR 中最小的 LEO,所以只要保证offset不出错,那消息就不会丢失或者重复消费。但是offset的维护并不是那么简单,它分为好几种方式。
offset的维护方式:
自动提交
enable.auto.commit:是否开启自动提交 offset 功能,消费者只在启动的时候去访问offset的值,如果将该值配置为false,就要手动提交offset,否则offset就不会更新。
auto.commit.interval.ms:自动提交 offset 的时间间隔
手动提交
commitSync(同步提交)
commitAsync(异步提交)
两者的相同点是:都会将本次 poll 的一批数据最高的偏移量提交;
不同点是:commitSync 阻塞当前线程,一直到提交成功,并且会自动失败重试(由不可控因素导致,也会出现提交失败);而 commitAsync 则没有失败重试机制,故有可能提交失败。
无论是同步提交还是异步提交 offset,都有可能会造成数据的漏消费或者重复消费。先提交 offset 后消费,有可能造成数据的漏消费;而先消费后提交 offset,有可能会造成数据的重复消费。
自定义存储offset
offset 的维护是相当繁琐的, 因为需要考虑到很多东西,例如消费者的 Rebalace。
如果开启了自动提交,那消费出现异常时,需要我们去维护一张表,去重新拉取此offset值的消息,重试消费,尝试几次后还是失败的话则此消息置为失败。
为了保证消息不丢失,建议使用手动提交偏移量。避免了拉取消息后,业务逻辑未处理完,自动提交了偏移量,但消费者挂了的情况。
At Most Once 语义:
将服务器 ACK 级别设置为 0,可以保证生产者每条消息只会被发送一次,即 At Most Once 语义。
此语义可以保证数据不重复,但是不能保证数据不丢失。
At Least Once 语义:
将服务器的 ACK 级别设置为-1(all),可以保证 Producer 到 Server 之间不会丢失数据,即 At Least Once 语义。
此语义可以保证数据不丢失,但是不能保证数据不重复。
Exactly Once 语义:
At Least Once + 幂等性 = Exactly Once
幂等性:所谓的幂等性就是指 Producer 不论向 Server 发送多少次重复数据, Server 端都只会持久化一条。
要启用幂等性,只需要将 Producer 的参数中 enable.idempotence 设置为 true 即可(此时 ack= -1)。 Kafka的幂等性实现其实就是将原来下游需要做的去重放在了数据上游。原理:开启幂等性的 Producer 在初始化的时候会被分配一个 PID,发往同一 Partition 的消息会附带 Sequence Number。而Broker 端会对<PID, Partition, SeqNumber>做缓存,当具有相同主键的消息提交时, Broker 只会持久化一条。
但是 PID 重启就会变化,同时不同的 Partition 也具有不同主键,所以幂等性无法保证跨分区、跨会话的 Exactly Once。(也就是说它只解决单次会话、单个分区里的消息重复问题)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。