kafka消息交付可靠性保障和精确,处理一次性语义的实现
一.消息交付可靠性保障:kafka对Prodcer和Consumer要处理的消息 提供什么样的承诺
- 最多一次(at most once):消息可能会丢失,但绝不会被重新发送。
- 至少一次(at least once):消息不会 丢失,但有可能被重复发送。
- 精确一次(exactly once):消息不会丢失,但也不会被重复发送
kafka默认提供的交付可靠性保障是第二种,即至少一次
- 消息已提交的含义:Broker成功"提交"消息且Producer接到Broker的应答才会认为该消息成功发送。
- 如果消息成功"提交",但是Broker的应答没有成功发送会Producer端(比如网络瞬时抖动)
- 它只能选择重试,就是再次发送相同的消息。这就是kafka默认提供至少一次可靠性保障的原因,但是会导致消息重复发送。
最多一次交付保障,让Producer禁止重试
- 消息要么写入成功,要么写入失败,但是绝对不会重复发送
- 适用于消息可以丢失,但是不能重复的场景
二.幂等性Producer
设置参数
- props.put("enable.idempotence",true);
- 或
- props.put(ProducerConfig.ENABLE_IDEMPOTENCLE_CONFIG,true);
原理:
- kafka自动 帮你做消息去重
- 经典的空间换时间的优化思路
- Broker端保存一些字段,当Producer发送具有相同字段值的消息后,Broker将他们丢弃;
作用范围:
- 只能保证单分区上的幂等性,即一个幂等性Producer能够保证某个主题上的一个分区上不出现重复消息,他无法实现多分区的幂等性
- 只能实现单会话上的幂等性,不能实现跨会话的幂等性,会话是指Producer进程的一次运行,重启以后作用就丢失。
事务 ##
- ACID
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔离性(Isolation)
持久性(Durability)
- 隔离性:并发执行的事务彼此互相隔离,互补影响
- 经典数据库教科书把隔离性称为可串行化(serializability)
- 每个事务都假装它是整个数据库中唯一的事务
隔离级别
- 已提交读(read commited) 隔离级别:当读取数据时,只能看到已提交的数据,即无脏读,当写入数据库时,只能覆盖掉已提交的数据,即无脏写
- kafka 在 read commited隔离级别上做事,能保证多条消息原子性的写入到目标分区,同时保证Consumer只能看到 事务成功提交的消息。
三.事务性Producer
实现多分区以及多会话上消息无重复
- 事务型Producer能够保证将消息原子性的写入到多个分区中。
- 这批消息要么全部写入成功,要么全部失败
设置事务型 Producer 的方法也很简单,满足两个要求即可:
- 开启enable.idempotence=true;
- 设置Producer端参数 transactional.id
//事务初始化
producer.initTransaction();
try{
//开启事务
producer.beginTransaction();
producer.send(record1);
producer.send(record2);
//事务提交
producer.commitTransaction();
}cath(KafkaException e){
//事务终止
producer.abortTransaction();
}
- 保证Record1和Record2被当作事务统一的提交到kafka,要么全部提交成功,要么全部写入失败
- 写入失败,kafka也会把他们写入到底层日志中,也就是说consumer也会看到这些消息。
四.Consumer 消费者端的修改:
isolation.level参数
read_uncommited.默认值
- Consumer能够读取到kafka写入的任何消息,事务型Producer提交事务还是终止事务,其写入的消息都是可读取的
read_comitted:Consumer
- 只会读取事务型Producer成功 提交事务写入的消息
版权声明:本文不是「本站」原创文章,版权归原作者所有 | 原文地址: