kafka生产者的幂等和事务处理

原创
05/05 09:28
阅读数 156

点击上方蓝字“极客运维”一起运筹帷幄

之前和大家聊过kafka是如何保证消息不丢失的,今天再讲讲在不丢消息的同时,如何实现精确一次处理的语义实现。

消息组件对消息的可靠性保障,常见的模式有 3 种:

  • 最多一次(at most once):消息可能会丢失,但不会重复
  • 至少一次(at least once):消息不会丢失,但有可能重复
  • 精确一次( exactly once):消息不会丢失,且不会重复,精准一次发送

kafka默认情况下,提供的是至少一次的可靠性保障。即broker保障已提交的消息的发送,但是遇上某些意外情况,如:网络抖动,超时等问题,导致Producer没有收到broker返回的数据ack,则Producer会继续重试发送消息,从而导致消息重复发送。

相应的,如果我们禁止Producer的失败重试发送功能,消息要么写入成功,要么写入失败,但绝不会重复发送。这样就是最多一次的消息保障模式。但对于消息组件,排除特殊业务场景,我们追求的一定是精确一次的消息保障模式。kafka通过幂等性(Idempotence)和事务(Transaction)的机制,提供了这种精确的消息保障。

幂等

这里就不多说幂等的含义了,不清楚的自己查下资料。Producer默认不是幂等性的,向分区发送数据时,可能会出现同一条消息被发送多次导致消息重复的情况。但只需增加一些参数,即可开启幂等性。

props.put(“enable.idempotence”, ture)
或者
props.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, true)

开启enable.idempotence后,kafka就会自动帮你做好消息去重的一系列工作。底层具体实现原理很简单,就是用空间换时间的优化思路,即在broker端多存一些字段来标识数据的唯一性。当Producer发送了具有相同字段值的消息后,broker会进行匹配去重,丢弃重复的数据。实际的代码没这么简单,但大致是这么个处理逻辑。

官方的这个幂等实现看似简单高效,但也存在他的局限性。他只能保证单分区上的幂等性,即一个幂等性Producer只能够保证某个topic的一个分区上不出现重复消息,无法实现多分区的幂等。此外,如果Producer重启,也会导致幂等重置。

事务

对于多分区保证幂等的场景,则需要事务特性来处理了。kafka的事务跟我们常见数据库事务概念差不多,也是提供经典的ACID,即原子性(Atomicity)、一致性 (Consistency)、隔离性 (Isolation) 和持久性 (Durability)。

事务Producer保证消息写入分区的原子性,即这批消息要么全部写入成功,要么全失败。此外,Producer重启回来后,kafka依然保证它们发送消息的精确一次处理。事务特性的配置也很简单:

  • 和幂等 Producer一样,开启 enable.idempotence = true
  • 设置 Producer端参数 transctional.id

事务Producer的代码稍微也有点不一样,需要调一些事务处理的API。数据的发送需要放在beginTransactioncommitTransaction之间。Consumer端的代码也需要加上isolation.level参数,用以处理事务提交的数据。示例代码:

producer.initTransactions();
try {
producer.beginTransaction();
producer.send(record1);
producer.send(record2);
producer.commitTransaction();
} catch (KafkaException e) {
producer.abortTransaction();
}

事务Producer虽然在多分区的数据处理上保证了幂等,但是处理性能上相应的是会有一些下降的。

依赖 redis 实现幂等

这里为什么还要额外讲通过依赖redis来实现幂等呢?

因为笔者在早期维护kafka相关应用时,那会 0.8 系列版本的kafka还没有这些自带的幂等事务特性,只能依靠开发者自己来实现。

常见的方式就是通过数据的业务属性来生成个uniqueId来维护到redis中,利用redis的高并发,高吞吐,分布式锁特性,让写入kafka多分区的数据前,先去redis中校验一下uniqueId等方式,来实现幂等。

得益于redis的高性能,在保证幂等同时,还能不让消息数据吞吐性能下降太多。当然,因为redis的依赖引入,也增加了架构的复杂度,从运维上来说也增加了整体的故障点,其中取舍需要自己来全局判断。

这次大概先介绍了下kafka的幂等各种实现方式,实际在事务,和依赖 redis 分布式锁来实现幂等的方式中,还要许多点值得我们深究来聊一下的,篇幅所限,后续再细讲。


相关推荐:

戳原文,点在看!

本文分享自微信公众号 - 极客运维(hypernetworker)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部