🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 幂等生产者和事务生产者 * 消息交付可靠性保障 * i.e. Kafka 对 Producer 和 Cosumer 要处理的消息提供什么样的承诺 * 常见承诺 * 最多一次(at most once):消息可能会丢失,但绝不会重复发送 * 至少一次(at least once):消息不会丢失,但可能重复发送 * 精确一次(exactly once):消息不会丢失,也不会重复发送 * Kafka 默认的可靠性保障为`至少一次` ## Kafka 的 exactly once * 通过以下两个机制 * 幂等性(Idempotence) * 事务(Trannsaction) ## 幂等性 * 数学概念 * 某些操作或函数能够被执行多次,但每次得到的结果都是不变的。 * CS 概念 * 在命令式 PL 中(e.g. C),若一个子程序是幂等的,那它必然不能修改系统状态 * 在函数式 PL 中(e.g. Scala),纯函数(pure function)天然幂等,不执行任何的 side effect * 幂等优势 * 可以安全重试 ## 幂等性 Producer * Kafka 中 Producer 默认不幂等 * V0.11.0.0 之后 可以指定 Producer 的幂等性 * props.put("enable.idempotence", true) * Kafka 自动帮你做消息的去重 * 具体原理 * 利用空间换时间的优化思路 * 在 Broker 保存一些字段 * 当 Producer 发送了相同呢字段值的消息后,Broker 会在后台将其丢弃 * 幂等性的作用范围 * 只能保证单分区上的幂等性,i.e. 一个幂等性 Producer 能够保证某个 Topic 的一个 Partitio 不出现重复消息 * 只能实现单会话上的幂等性,不能跨会话。i.e. 当重启 Producer 则不保证幂等性 * 对于多分区 & 多会话上做消息无重复的做法:使用`事务` ## 事务 * Kafka 的事务概念类似数据库领域的 ACID * 主要在 read committed 隔离级别上做事情 * read committed: 已提交读。当读取数据库时,只能看到已提交的数据,即无脏读。 ## 事务型 Producer * 保证消息原子性地写入到多个分区中 * 不怕进程重启 * 设置事务型 Producer * Producer 端参数:enable.idempotence = true * Producer 端参数:设置 transactional.id ``` Java producer.initTransactions(); try { producer.beginTransaction(); producer.send(record1); producer.send(record2); producer.commitTransaction(); } catch (KafkaException e) { producer.abortTransaction(); } ``` * Consumer 端读取事务型 Producer 发送的消息也需要调整 * 设置 isolation.level 值 * read_uncommitted:默认值,一切都会读。此处不合适。 * read_committed:Consumer 只会读取 Producer 成功提交事务写入的消息。 * 事务型 Producer 性能更差