Kafka -- 幂等性生产者 + 事务生产者
消息交付可靠性保障
- 消息交付可靠性保障:Kafka对Producer和Consumer要处理的消息所提供的承诺
- 常见的承诺
- 最多一次(at most once):消息可能会丢失,但绝不会被重复发送
- 至少一次(at least once):消息不会丢失,但有可能被重复发送
- 精确一次(exactly once):消息不会丢失,也不会被重复发送
- Kafka默认提供的交付可靠性保障:_至少一次_
- 只有Broker成功提交消息且Producer接到Broker的应答才会认为该消息成功发送
- 如果Broker成功提交消息,但Broker的应答没有成功送回Producer端,Producer只能选择重试
- 最多一次
- Kafka也可以提供最多一次交付可靠性保证,只需要让Producer禁止重试即可,但大部分场景下并不希望出现消息丢失
- 精确一次
- 消息不会丢失,也不会被重复处理,即使Producer端重复发送了相同的消息,Broker端也能自动去重
- 两种机制:幂等性、事务
幂等性
- 幂等原是数学中的概念:某些操作或者函数能够被执行多次,但每次得到的结果都是不变的
- 幂等操作:乘1,取整函数;非幂等操作:加1
- 计算机领域
- 在命令式编程语言(如C)中,如果一个子程序是幂等的,那它必然不能修改系统状态
- 在函数式编程语言(如Scala、Haskell)中,很多纯函数天然就是幂等的,不执行任何的Side Effect
- 幂等性的好处:可以安全地重试任何幂等性操作
幂等性Producer
- 在Kafka中,Producer默认不是幂等的,在0.11.0.0版本引入了幂等性Producer
- 默认情况下,Producer向Broker发送数据时,可能会出现同一条消息被发送多次,导致消息重复
- 升级为幂等性Producer
props.put("enable.idempotence", true)
或props.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, true)
- 基本原理
- 空间换时间,在Broker端多保存一些字段
- 当Producer发送了具有相同字段值的消息后,Broker能够自动发现这些重复消息,然后默默丢弃
- 作用范围
- 幂等性Producer只能保证单分区上的幂等性
- 即只能保证某个主题上的一个分区上不出现重复消息,无法实现多个分区的幂等性
- 幂等性Producer只能实现单会话上的幂等性,不能实现跨会话的幂等性
- 会话:Producer进程的一次运行,如果重启Producer进程,将丢失幂等性保证
- 如果要实现多分区或者多会话的消息无重复,可以采用事务Producer
- 幂等性Producer只能保证单分区上的幂等性
事务
- 数据库事务提供了ACID的安全性保障:Atomicity、Consistency、Isolation、Durability
- Kafka在0.11版本开始提供了对事务的支持,目前主要在Read Committed的隔离级别上做事情
- 保证多条消息原子性地写入目标分区,同时也保证Consumer只能看到事务成功提交的消息
事务Producer
- 事务Producer能够保证一批消息原子性地写入多个分区,这批消息要么全部写入成功,要么全部写入失败
- 事务Producer允许进程重启,Producer重启后,Kafka依然保证它们发送的消息的精确一次处理
- 升级为事务Producer
props.put("enable.idempotence", true)
props.put("transactional.id", "my-transactional-id")
- record1和record2会被当作一个事务统一提交到Kafka,要么全部提交成功,要么全部写入失败
- 即使写入失败,Kafka也会把它们写入到底层日志中,即Consumer还是会看到这些消息
- 因此在Consumer端,读取事务Producer发送的消息,需要设置isolation.level参数
- read_uncommitted
- 默认值,Consumer能够读取到Kafka写入的任何消息,不论事务Producer提交事务还是终止事务
- read_committed
- Consumer只会读取到事务Producer成功提交事务写入的消息,也能读取到非事务Producer写入的所有消息
- read_uncommitted
1 | producer.initTransactions(); |
小结
- 幂等性Producer和事务Producer都是Kafka社区为了实现精确一次处理语义所提供的工具,只是作用范围不同而已
- 幂等性Producer只能保证单分区、单会话上的消息幂等性;而事务Producer能够保证跨分区、跨会话的幂等性
- 事务Producer与幂等性Producer相比,性能更差
参考资料
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.