消息交付可靠性
什么是消息交付可靠性
??所谓的消息交付可靠性保障,是指Kafka为Producer和Consumer要处理的消息提供了什么样的承诺。常见的承诺右三种:
- 最多一次:消息可能丢失,但绝不会被重新发送。
- 至少一次:消息不会丢失,但有可能被重复发送。
- 精确一次:消息不会丢失,也不会被重新发送。
?? kafka默认是使用第二种”至少一次”,因为只有Broker成功“提交”消息且Producer接到Broker的应答才会认为该消息成功发送。如果此时,消息提交成功了,但是Broker的应答没有成功返回Producer端(比如发生了网络抖动),那么Producer就无法确定是否发送成功。因此它只能选择重试,此时就会导致消息重复发送。 ??kafka也可以提供最多一次交付保障,只需要让Producer禁止重试即可。通常情况下我们是不希望出现消息丢失的,但是有一些场景里偶尔的消息丢失是被允许的,不过消息重复是被绝对禁止的。此时使用最多一次交付保障就是比较好的。 ??kafka是如何做到精确一次的?它是通过两种机制:幂等性和事务完成的。
什么是幂等性
??幂等性指:某些操作或函数能够执行多次,但每次的结果都是不变的。举例任何数乘以1就是一个幂等操作,因为一个数乘以1一次和任意次的结果相同。 ??幂等性的最大优势在于我们可以安全的重试任何幂等性操作。
幂等性Producer
??在kafka中,Producer默认不是幂等性的,但我们可以创建幂等性的Producer。指定Producer幂等性的方法很简单,只需要设置一个参数:props.put(“enable.idempotence”,true)或props.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG,true)。 ??之后kafka会自动帮我们做消息去重,底层原理很简单,是经典的用空间换时间的优化思路,即在Broker端多保存一些字段。
幂等性Producer的作用范围
??首先:他只能保证单分区上的幂等性,即一个幂等性Producer能够保证某个主题的一个分区上不能出现重复,不能保证多个分区的幂等性。其次:他只能实现单会话上的幂等性,不能实现跨会话的幂等性。也就是重启Producer进程后幂等性保证就消失了。
如何实现多分区多会话的消息无重复?
??使用事务,或者依赖事务型Producer
kafka事务
??kafka主要在读已提交的隔离级别下工作。它能保证多条消息原子性的写入目标分区,也能保证Consumer只能看到事务成功提交的消息。
事务型Producer
??它能保证将消息原子性的写入多个分区中,并且不惧怕进程重启,重启之后还能保证发送消息的精确一次处理。 ??设置事务Producer方法:
- 设置enable.idempotence = true
- 设置Producer端参数transactional.id
代码使用:
producer.initTransactions();
try {
producer.beginTransaction();
producer.send(record1);
producer.send(record2);
producer.commitTransaction();
} catch (KafkaException e) {
producer.abortTransaction();
}
使用了事务Producer之后就要有事务的开启,提交回滚等东西了。 之后Consumer端也需要做一些修改:设置Consumer端的参数isolation.level参数的值。 它的取值有: 1:read_uncommitted:读未提交 2:read_committed:读已提交
|