[ java-006 ] Kafka事务(2)

186 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第18天,点击查看活动详情

继续上一章节,介绍kafka事务的原理特性

PID方法

首先要意识到的是,我们必须确保重复数据删除在服务器发生故障后工作,这意味着任何服务器作为分区的领导者都必须具有与前领导者相同的所有生产者 ID 信息。实现此目的的最简单方法是将 pid 字段添加到消息本身,以便在日志中将它们复制到关注者。。

每条消息将有三个新的整数字段:pid、sequence_number和生成。如果 PID 设置为 0,则服务器将忽略sequence_number和生成,以便与未实现幂等性的客户端兼容。服务器将维护 (pid, topic, partition) => (generation, sequence_number_highwater) 的映射。服务器将检查每封新传入邮件上的这些字段,并且仅当其序列号正好大于其高水位线一时,才会将邮件追加到日志中。此外,该代必须等于服务器存储的代数或大于一个代系。如上所述,增加生成将屏蔽来自“僵尸”生产者的任何消息。

PID问题

必须仔细考虑的一个细节是pids的过期。人们可能会想到的最简单的解决方案是将pids绑定到连接,这样我们就可以在连接断开时自动解除分配它们。但这并没有真正起作用,尽管由于pids必须在断开连接后幸存下来(实际上这是它们的主要观点)。

相反,此建议假设从颁发点开始,群集将具有一些固定的 pid 生存期,在此之后,pid 可供重用。还可以允许客户端在其lease_pid请求中定义自定义过期时间,但这需要更复杂的实现,因为所有复制都必须了解每个过期时间。服务器将按大约顺序发出pid,因此只有在发出40亿pids之后才会实际重用。

事务的producer

还可以通过开启kafka事务,来解决此问题

//初始化事务
producer.initTransactions();
try {
    //开启一个事务
    producer.beginTransaction();
    producer.send(record1);
    producer.send(record2);
    //提交
    producer.commitTransaction();
} catch (KafkaException e) {
    //出现异常的时候,终止事务
    producer.abortTransaction();
}

总结

这里其实提出了kafka实现事务的相关办法,例如使用pid或者自带的transaction,大家都可以参考下。kafka因为涉及到offset的提交,因此最好是自己来设置事务和offset的提交,如果直接使用自动提交,可能会导致数据丢失或者重复。这与kafka的机制相关,可能还有一些其它办法也能达到相同的效果,这里大家也可以选择合适业务场景的办法