首先kafka事务没办法做到这一点,事务只能保证以下几点:
producer发送多条消息,要么同时成功,要么同时失败;在没有提交事务之前,消息对消费者不可见,事务失败需要程序员自己调用kafka的 abort 回滚,kafka不会自己处理回滚,失败的情况下,这些已经发送的消息会被kafka标记为无效,消费者看不到
** 多说一句,kafka事务是分布式事务,比如 producer 发送多条事务,任意一条事务可能发送到 broker1 或者 broker2 ...
对于 消费消息 -> 重新发送kafka -> 提交offset 这个业务场景来说,kafka 事务能保证在程序出现异常的情况下,重新发送到 kafka 的消息无效,也就是消费者看不到这些消息,然后 offset 提交失败,也就是说消费者还是需要从上一次的offset继续消费消息
所以如何保证消费者不重复消费消息?
这个需要程序员自己去实现
比如发送消息的时候,可以为消息添加一条唯一 id,然后消费消息的时候,把这个id写入到数据库,每次消费消息先从数据库查询看有没有这个id,有的话就是已经消费过了,否则就是第一次消费
再者, 需要手动提交offset,而且提交的间隔不宜过长,比如可以设置每消费10条消息就提交offset,这样即使消费失败,最多也就需要判断10条消息的id,防止消息过多,判断这么多消息是否被消费过也是一种性能浪费