前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >kafka生产者的幂等和事务处理

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

作者头像
一条老狗
发布2020-05-09 14:55:39
2.2K0
发布2020-05-09 14:55:39
举报
文章被收录于专栏:极客运维极客运维

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

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

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

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

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

幂等

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

代码语言:javascript
复制
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参数,用以处理事务提交的数据。示例代码:

代码语言:javascript
复制
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 分布式锁来实现幂等的方式中,还要许多点值得我们深究来聊一下的,篇幅所限,后续再细讲。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-05-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 极客运维 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 幂等
  • 事务
  • 依赖 redis 实现幂等
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档