【问题标题】:How does kafka know whether to "roll forward or roll back" a transaction?kafka 如何知道是“前滚还是回滚”事务?
【发布时间】:2019-05-20 09:02:36
【问题描述】:

来自the exactly-once KIP,关于应用程序重启时生产者幂等性InitPidRequest

2.1 指定 TransactionalId 时如果设置了 transactional.id 配置,则此 TransactionalId 与 InitPidRequest,并映射到对应的PID登录 步骤 2a 中的事务日志。这使我们能够返回相同的 PID 将 TransactionalId 用于生产者的未来实例,因此 可以恢复或中止以前不完整的事务。

除了返回 PID 之外,InitPidRequest 还执行 以下任务:

  1. 增加 PID 的纪元,以便任何先前的僵尸 生产者的实例被隔离,无法继续前进 它的交易。

  2. 恢复(前滚或后滚)任何 生产者的前一个实例未完成交易。 InitPidRequest 的处理是同步的。一旦回来, 生产者可以发送数据并开始新的交易。

当生产者失败并再次启动并执行InitPidRequest时,最后一个事务“前滚”(我猜这意味着已提交)或“回滚”是什么情况?这是如何控制的?

【问题讨论】:

    标签: apache-kafka kafka-producer-api


    【解决方案1】:

    使 Kafka 能够实现这一点的关键组件是 事务协调器。这是作为您提到的 KIP 的一部分引入的。事务协调器由代理构建,作为初始化过程的一部分,并在内存中维护以下信息:

    1. TransactionalId 到分配的PID 的映射、当前纪元号(Unix 时间戳)和事务超时值
    2. PIDPID 指示的生产者当前正在进行的事务状态、参与者主题分区以及此状态的最后更新时间的映射

    现在,回答您关于前滚或后滚交易的问题

    当生产者失败并重新启动时,如果生产者带有非空的TransactionalId(由生产者应用程序作为配置参数提供),它会向事务协调器发送一个新的InitPidRequest

    事务协调器收到此请求后会检查内存映射中是否已经存在具有提供的TransactionalId 的条目(上面的第 1 点)。如果存在映射,它将在第二个内存映射(上面的第 2 点)中查找PID,以检查是否有针对该PID 的任何正在进行的事务:

    • 如果有一个正在进行的事务处于启动状态,即BEGIN,那么事务将被中止 (注意这是回滚版本
    • 如果有一个正在进行的事务已经开始并且在PREPARE_ABORTPREPARE_COMMIT 中,那么事务协调器将等待事务通过COMPLETE_ABORT (回滚版本)或COMPLETE_COMMIT前滚版本)。

    此后,事务协调器以最新的PIDTransactionalId 的纪元时间戳进行响应,然后生产者可以开始发送新事务。

    我试图将解释保持在最低限度,但如果您对更多细节感兴趣,那么这里是 detailed design document 供您参考。

    我希望这会有所帮助!

    【讨论】:

    • 这是一个绝妙的答案。谢谢。
    • @b15 - 谢谢!我很高兴你发现它很有用。 :)
    猜你喜欢
    • 1970-01-01
    • 2018-05-27
    • 1970-01-01
    • 2015-03-06
    • 1970-01-01
    • 1970-01-01
    • 2017-02-14
    • 1970-01-01
    • 2012-07-21
    相关资源
    最近更新 更多