kafka对producer和consumer要处理的消息提供3中承诺:
at most once: 最多一次,消息可能会丢失,不会重复发送
at least once: 至少一次,消息不会丢失,可能重复发送。Kafka 默认这种方式,当网络瞬时抖动,broker的应答无法成功发送给producer端,那么producer不确定消息写入是否成功,会选择重新发送一次。
exactly once: 精确一次, 消息不会丢失,不会重复发送
你可能会以为最好是exactly once, 不过要做到精确一次,是要牺牲空间和性能的,那么kafka是怎么做到的呢? 幂等性和事务 机制。
幂等型Producer, props.put("enable.idempotence", true). kafka自动帮你做消息去重。
思路大致是这样的: broker端多保存一些字段,当producer发送了相同的消息时,自动丢弃掉。不过这可不是万能的,1. 单分区,它只能保证单分区上不重复 2. 单会话,producer进程如果重启了,也保证不了幂等性。
那怎么才能解决上面的问题呢?
事务型Producer
设置参数:
props.put("enable.idempotence", true);
props.put("transactional.id", "my transaction id");
事务代码:
producer.initTransactions();
try {
producer.beginTransaction();
producer.send(msg);
producer.commitTransaction();
} catch (KafkaException e) {
producer.abortTransaction();
}
consumer接收的时候,
设置consumer端参数:
props.put("isolation.level", read_committed); //默认是read_uncommitted