kafka 事务代码实现(生产者到server端的事务)
kafka的事务指的是2个点 ① 生产者到kafka服务端的事务保障 ②消费者从kafka拉取数据的事务
kafka提供的事务机制是 第①点, 对于第②点来说 只能自己在消费端实现幂等性。
我们来介绍第①点, 因为生产者producer写到kafka可能会出现消息重复,比如 设置ack=all,写入到kafka的leader时,leader挂掉了,
没有及时反馈ack,导致生产者再次发送消息就会出现重复消息落盘。这种情况可以设置kafka的属性用来开启幂等。但是这种幂等
只能保证 producer没有挂掉的情况下,因为幂等的原理是 kafka缓存了一份 pid,partition,seqnumber 的数据,如果命中则说明之前缓存了,
但是如果producer挂掉了重启后,它的pid就会变化,partition也有可能变化,就会导致消息会出现重复状况。所以kafka 0.11版本加入了事务机制
开启时事务后,会存在 transaction_id , 封装成( transaction_id, pid,partition,seqnumber, 消费到哪条记录等等) 保存在kafka上,如果producer 挂了重新
启动的时候,会自动寻找kafka中的这个 transaction_id,找到的话就会恢复到挂掉之前的状态 ,然后进行消费。kafka事务保证了 要么全部成功,要么全部失败。
还有一个很重要的点是 要在consumer端 设置 isolation.level 为 read_committed状态,它默认是read_uncommitted状态,这是什么意思呢? 接下来详细说明一下:
目前producer是双线程设计,后台的Sender线程负责实际的消息发送。当Sender线程构造消息batch发送时,它会尝试去读取事务状态,如果发现已经abort,则立即将未发送的batch全部fail掉——这就是为什么你注释Thread.sleep后则不能发送的原因。当你加入了Thread.sleep之后batch发送时主线程在休眠,尚未执行到abortTransaction,故Sender线程成功地发送了消息到Kafka broker。
另外,你需要为consumer端配置isolation.level = read_committed。这样不管哪种情况你都不会读取到任何未提交的消息。默认是read_uncommitted,即使abort的消息,只要是成功发送到Kafka了,consumer就能读取到。
1、也就是开启事务之后,生产者调用send发送数据时他就会直接向kafka插入数据,只不过是这个数据后面追加了一个状态,这个状态是read_uncommited代表未提交,只有producer调用了commitTransaction时候 这些数据在kafka中才会都标记为read_commited。
producer实现代码如下:
public class producer {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Properties props = new Properties();
props.put("bootstrap.servers","hadoop102:9092,hadoop103:9092,hadoop104:9092");
props.put("key.serializer","org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer","org.apache.kafka.common.serialization.StringSerializer");
props.put("acks","all");
props.put("retries","2");
props.put("batch.size","16384");
props.put("transactional.id","tran-wb2"); //事务ID,开启事务下面幂等也要开启
props.put("enable.idempotence", "true"); //开启幂等
// 一定要在消费者方设置 isolation.level为 read_committed,表示只读取已提交事务状态的记录
Producer<Object, Object> producer = new KafkaProducer<>(props);
producer.initTransactions();
producer.beginTransaction();
try {
for (int i = 0; i <100 ; i++) {
Future<RecordMetadata> first = producer.send(new ProducerRecord<>("first", i + "sad ", i + 1 + "s d"));
//first.get(); 加上get可以实现同步发送操作
if (i==20){
throw new RuntimeException("测试异常回滚");
}
}
} catch (RuntimeException e){
System.out.println(e.toString());
producer.abortTransaction(); //出现异常,就进行回滚,这样所有消息都会失败
producer.close();
return;
}
producer.commitTransaction(); //没有异常就 事务提交
producer.close();
}
}
消费者代码
public class consumer {
public static void main(String[] args) throws InterruptedException {
Properties properties = new Properties();
properties.put("bootstrap.servers", "hadoop102:9092,hadoop103:9092,hadoop104:9092");
properties.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
properties.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
properties.put("group.id", "wangbingsaa");
properties.put("isolation.level", "read_committed"); //一定要设置 只拉取 已提交事务状态的记录,这样无论什么条件都可以
// properties.put("auto.offset.reset","earliest"); //设置拉取的位置
properties.put("enable.auto.commit", "false"); //关闭自动提交
properties.put("auto.commit.interval.ms", "1000"); //自动提交间隔
Consumer<String, String> consumer = new KafkaConsumer<>(properties);
consumer.subscribe(Collections.singletonList("first"));
ConsumerRecords<String, String> records = consumer.poll(4000); //如果拉取时长超过4000毫秒 就不拉取
for (ConsumerRecord<String, String> record : records) {
System.out.printf("offset = %d, partitoon = %d key = %s, value = %s%n", record.offset(), record.partition(),record.key(), record.value());
}
consumer.commitSync(); //手动提交
}
}
kafka 事务代码实现(生产者到server端的事务)的更多相关文章
- HBase 协处理器编程详解第一部分:Server 端代码编写
Hbase 协处理器 Coprocessor 简介 HBase 是一款基于 Hadoop 的 key-value 数据库,它提供了对 HDFS 上数据的高效随机读写服务,完美地填补了 Hadoop M ...
- JS学习十四天----server端运行JS代码
server端运行JS代码 话说,当今不在client使用JS代码才是稀罕事.因为web应用的体验越来越丰富,client用JS实现的逻辑也越来越多,这造成的结果就是某些差点儿一致的逻辑须要在clie ...
- 上机题目(0基础)- Java网络操作-Socket实现client和server端通信二(Java)
上一节实现了client像server端发送请求.本节将实现server端向client回传信息.实现原理非常easy,在原来的基础上.在server端实现输出流,在client实现输入流就可以,详细 ...
- golang如何优雅的编写事务代码
目录 前言 需求 烂代码示例 重构套路 一.提前返回去除if嵌套 二.goto+label提取重复代码 三.封装try-catch统一捕获panic 前言 新手程序员概有如下特点 if嵌套特别多.重复 ...
- Kafka源码分析(三) - Server端 - 消息存储
系列文章目录 https://zhuanlan.zhihu.com/p/367683572 目录 系列文章目录 一. 业务模型 1.1 概念梳理 1.2 文件分析 1.2.1 数据目录 1.2.2 . ...
- Hadoop基于Protocol Buffer的RPC实现代码分析-Server端
http://yanbohappy.sinaapp.com/?p=110 最新版本的Hadoop代码中已经默认了Protocol buffer(以下简称PB,http://code.google.co ...
- Hadoop基于Protocol Buffer的RPC实现代码分析-Server端--转载
原文地址:http://yanbohappy.sinaapp.com/?p=110 最新版本的Hadoop代码中已经默认了Protocol buffer(以下简称PB,http://code.goog ...
- 搭建分布式事务组件 seata 的Server 端和Client 端详解(小白都能看懂)
一,server 端的存储模式为:Server 端 存 储 模 式 (store-mode) 支 持 三 种 : file: ( 默 认 ) 单 机 模 式 , 全 局 事 务 会 话 信 息 内 存 ...
- Linux下的C Socket编程 -- server端的继续研究
Linux下的C Socket编程(四) 延长server的生命周期 在前面的一个个例子中,server在处理完一个连接后便会立即结束掉自己,然而这种server并不科学啊,server应该是能够一直 ...
随机推荐
- Tomcat服务器和Servlet版本的对应关系
Tomcat服务器和Servlet版本的对应关系 Servlet 程序从2.5版本是现在世面使用最多的版本(xml配置) 到了Servlet3.0后.就是注解版本的Servlet使用
- Java多线程专题6: Queue和List
合集目录 Java多线程专题6: Queue和List CopyOnWriteArrayList 如何通过写时拷贝实现并发安全的 List? CopyOnWrite(COW), 是计算机程序设计领域中 ...
- el表达式中的${param}用法
el表达式中的${param}? 1. 2. ${param.name} 等价于 request.getParamter("name"),这两种方法一般用于服务器从页面或者客户端获 ...
- 微服务架构 | 7.2 构建使用 JWT 令牌存储的 OAuth2 安全认证
目录 前言 1. JWT 令牌存储基础知识 1.1 JSON Web Token 2. 构建使用 JWT 令牌存储的 OAuth2 服务器 2.1 引入 pom.xml 依赖文件 2.2 创建 JWT ...
- 实现表单input文本框不可编辑的三种方法
感谢原文作者:青灯夜游 原文链接:https://www.php.cn/div-tutorial-413133.html 目录 问题 实现方式 1.οnfοcus=this.blur() 2.read ...
- 如何修改TOMCAT的默认主页为你自己项目的主页
感谢作者:xxs673076773 原文链接:https://www.iteye.com/blog/xxs673076773-1134805 (最合适的) 最直接的办法是,删掉tomcat下原有Roo ...
- ListIterator特有的方法
import java.util.ArrayList; import java.util.List; import java.util.ListIterator; /* 迭代 listIterator ...
- Ext原码学习之Ext.js
1 // JavaScript Document 2 //定义全局Ext变量 3 var Ext = Ext ||{}; 4 Ext._startTime = new Date().getTime() ...
- 模型融合——stacking原理与实现
一般提升模型效果从两个大的方面入手 数据层面:数据增强.特征工程等 模型层面:调参,模型融合 模型融合:通过融合多个不同的模型,可能提升机器学习的性能.这一方法在各种机器学习比赛中广泛应用, 也是在比 ...
- 了解selenium这个工具
selenium 也不是简单一个工具,而是由几个工具组成,每个工具都有其特点和应用场景. selenium IDE selenium IDE 是嵌入到Firefox浏览器中的一个插件,实现简单的浏 ...