Kafka 幂等,事物,消息可靠性

本文结合在使用Kafka中的使用,和遇到的问题

1.Kafka中如何保障发送消息的可靠性?

首先我们在创建一个Producer是,可以设置的一些参数如下:


  • 1(默认):这意味着producer在ISR中的leader已成功收到的数据并得到确认后发送下一条message。如果leader宕机了,则会丢失数据。
  • 0:这意味着producer无需等待来自broker的确认而继续发送下一批消息。这种情况下数据传输效率最高,但是数据可靠性确是最低的。
  • -1:producer需要等待ISR中的所有follower都确认接收到数据后才算一次发送完成,可靠性最高。但是这样也不能保证数据不丢失,比如当ISR中只有leader时(前面ISR那一节讲到,ISR中的成员由于某些情况会增加也会减少,最少就只剩一个leader),这样就变成了acks=1的情况。

request.required.acks=1 此种情况下可能会有数据的丢失,如果leader宕机的话,但是此种设置的情况下,效率应该是最高的


ISR的理解

Kafka 0.10.x版本后移除了replica.lag.max.messages参数,只保留了replica.lag.time.max.ms作为ISR中副本管理的参数。为什么这样做呢?replica.lag.max.messages表示当前某个副本落后leaeder的消息数量超过了这个参数的值,那么leader就会把follower从ISR中删除。假设设置replica.lag.max.messages=4,那么如果producer一次传送至broker的消息数量都小于4条时,因为在leader接受到producer发送的消息之后而follower副本开始拉取这些消息之前,follower落后leader的消息数不会超过4条消息,故此没有follower移出ISR,所以这时候replica.lag.max.message的设置似乎是合理的。但是producer发起瞬时高峰流量,producer一次发送的消息超过4条时,也就是超过replica.lag.max.messages,此时follower都会被认为是与leader副本不同步了,从而被踢出了ISR。但实际上这些follower都是存活状态的且没有性能问题。那么在之后追上leader,并被重新加入了ISR。于是就会出现它们不断地剔出ISR然后重新回归ISR,这无疑增加了无谓的性能损耗。而且这个参数是broker全局的。设置太大了,影响真正“落后”follower的移除;设置的太小了,导致follower的频繁进出。无法给定一个合适的replica.lag.max.messages的值,故此,新版本的Kafka移除了这个参数。

注:ISR中包括:leader和follower。

上面一节还涉及到一个概念,即HW。HW俗称高水位,HighWatermark的缩写,取一个partition对应的ISR中最小的LEO作为HW,consumer最多只能消费到HW所在的位置。另外每个replica都有HW,leader和follower各自负责更新自己的HW的状态。对于leader新写入的消息,consumer不能立刻消费,leader会等待该消息被所有ISR中的replicas同步后更新HW,此时消息才能被consumer消费。这样就保证了如果leader所在的broker失效,该消息仍然可以从新选举的leader中获取。对于来自内部broKer的读取请求,没有HW的限制。


Leader选举

一条消息只有被ISR中的所有follower都从leader复制过去才会被认为已提交。这样就避免了部分数据被写进了leader,还没来得及被任何follower复制就宕机了,而造成数据丢失。而对于producer而言,它可以选择是否等待消息commit,这可以通过request.required.acks来设置。这种机制确保了只要ISR中有一个或者以上的follower,一条被commit的消息就不会丢失。



### 等性的实现原理 Kafka等性特性通过引入唯一标识符(PID)和序列号机制,确保生产者在发送消息时,即使发生重试,也不会导致消息重复。每个生产者实例都会被分配一个唯一的 PID,而每条发送的消息都会携带一个递增的序列号,用于标识该消息在发送顺序中的位置。Broker 会为每个 `<PID, 分区>` 组合维护一个序列号窗口,记录最近收到的序列号。当收到一条消息的序列号小于或等于当前记录值时,Broker 会判断该消息为重复发送,并直接丢弃它,同时返回成功确认给生产者(模拟写入成功)[^5]。 这种机制确保了即使在网络不稳定或发生故障的情况下,Kafka 仍然能够避免消息重复的问题。例如,在模拟网络故障的测试方案中,当生产者发送消息并触发重试后,消费者最终只会收到一条消息,验证了等性机制的有效性 [^4]。 ### 配置与使用 Kafka等性功能是在 0.11.0.0 版本中引入的,生产者默认不是等性的,但可以通过配置启用。启用等性的生产者配置如下: ```java Properties props = new Properties(); props.put("bootstrap.servers", "localhost:9092"); props.put("acks", "all"); props.put("retries", 0); props.put("enable.idempotence", true); // 启用等性 props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer"); props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer"); Producer<String, String> producer = new KafkaProducer<>(props); ``` 通过上述配置,Kafka 生产者将启用等性支持,从而确保消息的精确一次交付 [^1]。 ### 适用场景 Kafka等性适用于简单的消息发送场景,其中只需要确保消息不会重复。然而,对于需要跨分区、跨会话的原子性操作的复杂场景,则应考虑使用事务特性。等性与事务特性之间的选择需要在可靠性和性能之间做出权衡,选择最适合业务场景的配置 [^1]。 ### 相关问题 1. Kafka等性如何解决消息重复问题? 2. 如何在 Kafka 中启用等性? 3. Kafka等性与事务特性有何区别? 4. Kafka 等性对性能的影响有多大? 5. Kafka 等性在哪些场景下最有效?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值