kafka如何知道是否"roll forward or roll back"一个事务?

How does kafka know whether to "roll forward or roll back" a transaction?

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

2.1 When an TransactionalId is specified If the transactional.id configuration is set, this TransactionalId passed along with the InitPidRequest, and the mapping to the corresponding PID is logged in the transaction log in step 2a. This enables us to return the same PID for the TransactionalId to future instances of the producer, and hence enables recovering or aborting previously incomplete transactions.

In addition to returning the PID, the InitPidRequest performs the following tasks:

  1. Bumps up the epoch of the PID, so that the any previous zombie instance of the producer is fenced off and cannot move forward with its transaction.

  2. Recovers (rolls forward or rolls back) any transaction left incomplete by the previous instance of the producer. The handling of the InitPidRequest is synchronous. Once it returns, the producer can send data and start new transactions.

当生产者失败重新启动并执行InitPidRequest时,最后一个事务'rolled forward'(我猜这意味着committed)或'rolled back'是什么情况?这是如何控制的?

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

  1. TransactionalId到分配的PID的映射,当前纪元号(Unix时间戳)和事务超时值
  2. PIDPID、参与者topic-partitions和上次更新此状态的时间[=58]指示的生产者当前正在进行的交易状态的映射=]

现在,回答您关于前滚或后退事务的问题

当生产者失败并重新启动时,如果生产者带有 non-empty TransactionalId(作为配置参数由生产者应用程序)。

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

  • 如果有一个 on-going 事务处于启动状态,即 BEGIN,则该事务将被中止 (:这是rolled-back版本)
  • 如果有一个 on-going 交易已经开始并且处于 PREPARE_ABORTPREPARE_COMMIT,那么交易协调器将等待交易完成 COMPLETE_ABORT (rolled-back 版本) 或 COMPLETE_COMMIT (rolled-forward版本).

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

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

希望对您有所帮助!