springboot2.x +kafka使用和源码分析四(kafka事务)

SpringBoot集成Kafka详解 我们知道,kafka中每个topic被划分为多个分区,那么生产者将消息发送到topic时,具体追加到哪个分区呢?这就是所谓的分区策略,Kafka 为我们提供了默认的分区策略,同时它也支持自定义分区策略。其路由机制为:1.若发送消息时指定了分区(即自定义分区策略),则直接将消息append到指定分区; 阅读详情

kafka对于事务的支持(0.11.0.0客户端库开始添加了对事务的支持,kafka针对于事务机制新增名为 __transaction_state topic用以保存数据):

  • KafkaTransactionManager:与spring提供的事务机制一起使用(@Transactional,TransactionTemplate等等)。

  • 使用 KafkaMessageListenerContainer 事务性监听容器(消费者保证消费Exactly Once仅消费处理一次)

  • 使用KafkaTemplate

如果需要开启事务机制,使用默认配置需要在yml添加spring.kafka.producer.transaction-id-prefix配置。

或者自己初始化bean在上述KafkaProducerConfigure中添加


    /**
     * 构建生产者工厂类
     */
    @Bean
    public ProducerFactory<Integer, String> producerFactory() {

        Map<String, Object> configs = producerConfigs();

        DefaultKafkaProducerFactory<Integer,String>  producerFactory =  new DefaultKafkaProducerFactory(configs,new IntegerSerializer(),new StringSerializer());

        //设置事务Id前缀 开启事务
        producerFactory.setTransactionIdPrefix("tx-");
        return producerFactory;
    }

    @Bean
    public KafkaTransactionManager<Integer, String> kafkaTransactionManager(ProducerFactory<Integer, String> producerFactory) {
		return new KafkaTransactionManager<>(producerFactory);
	}

将KafkaTransactionManager注入到spring中。如果开启的事务,则后续发送消息必须使用@Transactional注解或者使用kafkaTemplate.executeInTransaction() ,否则抛出java.lang.IllegalStateException: No transaction is in process; possible solutions: run the template operation within the scope of a template.executeInTransaction() operation, start a transaction with @Transactional before invoking the template method, run in a transaction started by a listener container when consuming a record

源码分析:

   /**
     *信息的发送最终会执行此方法
     */
    protected ListenableFuture<SendResult<K, V>> doSend(final ProducerRecord<K, V> producerRecord) {
        //判断是否开启线程
        if (this.transactional) {
            //判断当前消息是通过事务的方式发送
            Assert.state(inTransaction(),
                    "No transaction is in process; "
                            + "possible solutions: run the template operation within the scope of a "
                            + "template.executeInTransaction() operation, start a transaction with @Transactional "
                            + "before invoking the template method, "
                            + "run in a transaction started by a listener container when consuming a record");
        }
        //获取Producer 对象用于发送消息
        final Producer<K, V> producer = getTheProducer();
        this.logger.trace(() -> "Sending: " + producerRecord);
        //定义发送结果回调对象
        final SettableListenableFuture<SendResult<K, V>> future = new SettableListenableFuture<>();
        producer.send(producerRecord, buildCallback(producerRecord, producer, future));
        //是否开启自动刷新
        if (this.autoFlush) {
            flush();
        }
        this.logger.trace(() -> "Sent: " + producerRecord);
        return future;
    }

    /**
     *判断方法的执行是否在事务中
     */
    public boolean inTransaction() {
        return this.transactional && (
                //当前执行线程在ThreadLocal中是否保存过producer如果有说明已在事务中
                this.producers.get() != null
                || TransactionSynchronizationManager.getResource(this.producerFactory) != null
                || TransactionSynchronizationManager.isActualTransactionActive());
    }

 

1:本地事务支持(不支持事务嵌套)

 /**
     * 测试kafka事务机制
     */
    @RequestMapping("sendSyncPersonInfoStrByTransaction")
    public void sendSyncPersonInfoStrByTransaction(){
        JSONObject j = new JSONObject();

        j.put("name","张三测试事务");
        j.put("sex","男");
        j.put("age",18);

        Integer key = new Random().nextInt(100);

        /**
         * 如果KafkaTransactionManager正在进行一个事务,则不使用它。而是使用新的“嵌套”事务。
         */
        boolean flag =kafkaTemplate.executeInTransaction(t->{
    
                //如果在这里这些任何异常抛出 代表此次事务需要进行数据回滚

                t.send("springboot_test_topic",key,j.toJSONString())
                        .get(5, TimeUnit.SECONDS);

                j.put("sex","女");
                t.send("springboot_test_topic",key+10,j.toJSONString())
                        .get(5, TimeUnit.SECONDS);
                int i = 0/0;

                return true;    
           
        });

        System.out.println(flag);

    }

运行上述测试代码,当代码运行报错( int i = 0/0; 除零异常)时,不会发送任何信息到kafka中

查看executeInTransaction方法源码可以知道

public <T> T executeInTransaction(KafkaOperations.OperationsCallback<K, V, T> callback) {

        Assert.notNull(callback, "'callback' cannot be null");
        Assert.state(this.transactional, "Producer factory does not support transactions");
        //在ThreadLocal保证线程安全
        Producer<K, V> producer = this.producers.get();
        Assert.state(producer == null, "Nested calls to 'executeInTransaction' are not allowed");

        String transactionIdSuffix;
        if (this.producerFactory.isProducerPerConsumerPartition()) {
            transactionIdSuffix = TransactionSupport.getTransactionIdSuffix();
            TransactionSupport.clearTransactionIdSuffix();
        }
        else {
            transactionIdSuffix = null;
        }
        //创建producer 事务的操作由此对象处理
        producer = this.producerFactory.createProducer(this.transactionIdPrefix);

        try {
            //开启事务
            producer.beginTransaction();
        }
        catch (Exception e) {
            //如果发送异常关闭producer 不占用资源
            closeProducer(producer, false);
            throw e;
        }
        //将
        this.producers.set(producer);
        try {
            //执行业务代码
            T result = callback.doInOperations(this);
            try {
                //提交事务
                producer.commitTransaction();
            }
            catch (Exception e) {
                throw new KafkaTemplate.SkipAbortException(e);
            }
            return result;
        }
        catch (KafkaTemplate.SkipAbortException e) { // NOSONAR - exception flow control
            throw ((RuntimeException) e.getCause()); // NOSONAR - lost stack trace
        }
        catch (Exception e) {
            //发生异常 终止事务
            producer.abortTransaction();
            throw e;
        }
        finally {
            //设置事务id
            if (transactionIdSuffix != null) {
                TransactionSupport.setTransactionIdSuffix(transactionIdSuffix);
            }
            //在ThreadLocal移除Producer
            this.producers.remove();
            //关闭资源
            closeProducer(producer, false);
        }
    }

2:使用@Transactional(transactionManager = "kafkaTransactionManager",rollbackFor = Exception.class) 使用

@RequestMapping("sendSyncPersonInfoStrByTransactionZJ")
    @Transactional(transactionManager = "kafkaTransactionManager",rollbackFor = Exception.class)
    public void sendSyncPersonInfoStrByTransactionZJ(){
        JSONObject j = new JSONObject();

        j.put("name","张三测试事务");
        j.put("sex","男");
        j.put("age",18);

        Integer key = new Random().nextInt(100);

        kafkaTemplate.send("transaction_test_topic",20,j.toJSONString());

        j.put("sex","女");
        kafkaTemplate.send("transaction_test_topic",10,j.toJSONString());

//        int i = 0/0;

    }

 

3:嵌套事务

在业务系统可能会存在以下的需求,当发送一条消息时,需要记录一条日志到业务数据库(mysql)中,那么这里面存在两种数据源(kafka,mysql)。这也就是我们说的嵌套事务,那么如何保证去数据一致性。spring提供了自己的解决方案(需要结合Consumer的Listen,后续表明)

Demo项目github地址:https://github.com/fangyuan94/kafkaDemo

no transaction is in progresss 问题描述: spring mvc 项目在执行查询功能的时候 后台报错如下: javax.persistence.TransactionRequiredException:no transaction is in progress ............ 后来找到原因是因为链接的资源有问题也就是sessionFactory所映射到配置资源链接的资源库有问题,修改之后没有问题,后来进行原因查... 阅读详情

相关推荐

SpringBoot系列之集成 Kafka 实现事务机制:从配置到实战

本文详细介绍了Spring Boot集成Kafka实现事务机制的实践方案。文章涵盖从环境配置到核心代码实现,重点讲解了如何通过Kafka事务管理器确保生产、消费和偏移量提交的原子性。主要内容包括:引入Spring Kafka依赖、关键配置参数说明、带事务的消息发送与消费代码示例、事务管理器配置以及事务回滚验证方法。同时提供了性能优化建议和监控方案,强调结合Saga模式或Outbox模式实现跨服务事务一致性。该方案适用于需要Exactly-Once语义的生产环境,能有效解决分布式系统中的数据一致性问题。

Nicky's blog 1048

no transaction is in progress

主要:<prop key="hibernate.allow_update_outside_transaction">true</prop> <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ..

正怒月神的博客 3355

springboot整合kafka

业务中需要使用到异步消息队列,为了快速搭建一个消息中间件,这里选了kafka,一方面是kafka搭建比较简单,而且这个中间件比较成熟,而且对于大数据量的消息支持很好,下面首先说说kafka的安装,我这里演示一下在linux上如何搭建kafka, 1、首先安装zookeeper,kafka的启动需要依赖zookeeper,zookeeper安装比较简单,基本上就是上传压缩包,解压,然后启动即可, ...

congge 6万+

kafka 使用及学习过程中的爬坑记录

文章目录Producer factory does not support transactions解决方案Must set retries to non-zero when using the idempotent producer.解决方案Must set acks to all in order to use the idempotent producer. Otherwise we cannot guarantee idempotence.No transaction is in process;

做一个有思想的技术人 3805

AUTOSAR E2E Protocol实战:Profile1到Profile5的配置差异与最佳实践

本文深入解析AUTOSAR E2E Protocol中Profile1到Profile5的核心配置差异与适用场景。针对经典CAN、CAN FD及以太网等不同总线,详细对比了计数器、CRC、DataID等关键参数,并结合实战代码与配置示例,为工程师根据功能安全等级、数据长度与带宽限制选择最佳Profile提供了清晰的选型路径与工程实践指南。

milk5的博客 940

三维点云孔洞修复(附Python代码和公共点云数据集链接)

(1)物体自身缺失(2)物体自身形状复杂,很多凹凸面不够规则甚至存在空腔,空腔内部无法被三维激光扫描仪扫描到(3)物体部分区域对激光扫描不敏感,未被扫描上(4)扫描仪的扫描稳定性。

yanghl1215的博客 6950

关于no transaction is in progress错误的解决方法

在使用spring +jpa开发中 结构dao+service+action三层 dao继承basedao basedao中写了方法 public T merge(T entity) { T returnObj = this.getJpaTemplate().merge(entity); this.getJpaTemplate().flush(); return r

自由空间 4万+

5分钟搞定!用MCU GPIO实现零功耗一键开关机电路(附完整原理图)

本文详细介绍了如何利用MCU GPIO设计零功耗一键开关机电路,适用于便携式设备和电池供电项目。通过软硬件结合的方式,实现关机状态下的真正零功耗,同时提供智能开关机控制。文章包含完整原理图、元件选型指南和实际搭建技巧,帮助开发者在5分钟内完成高效电源管理方案。

weixin_28339967的博客 341

Kafka生产者源码解析(一)——KafkaProducer

版本:Spring-Kafka2.3.3 一、源码探析入口 //发送消息,回调结果 ListenableFuture<SendResult<String, Object>> future = kafkaTemplate.send(topic, obj);

齐天小圣^O^ 的博客 1542

Matlab之fdesign的应用说明

fdesign 是 MATLAB 中用于数字滤波器设计的工具(属于),它提供了一种系统化的方式来定义滤波器参数并生成相应的滤波器。指定滤波器的频率、幅度等参数。例如,设计一个低通滤波器:Fs = 1000;% 采样率 (Hz)% 通带截止频率% 阻带截止频率Apass = 1;% 通带衰减 (dB)Astop = 60;% 阻带衰减 (dB)

嵌入式老牛的博客 1052

Dify+MCP Server打造禅道AI智能助手

Dify AI与MCP Server结合打造的禅道AI智能助手,实现了项目管理智能化升级。该方案通过大语言模型和自动化工作流,提供四大核心功能:1)自动化报表生成,支持多维度数据统计与可视化;2)禅道系统管理操作,简化产品/项目/任务管理流程;3)基于知识库的智能问答系统;4)数据库灵活查询与可视化输出。系统采用分层架构,通过MCP协议实现AI与数据源解耦,解决了传统禅道在数据孤岛、工具碎片化等问题。实际应用验证了其在用户管理、任务创建、Bug处理等场景的高效性,显著提升了项目管理效率。

oNew_Lifeo的博客 1708

springboot使用kafka事务

如上:消费者没打印消息,说明消息没发送成功,并且前面会报错org.apache.kafka.common.KafkaException: Failing batch since transaction was aborted 的错误,说明事务生效了。kafka事务属性是指一系列的生产者生产消息和消费者提交偏移量的操作在一个事务,或者说是是一个原子操作),同时成功或者失败。配置开启事务后,使用大体有两种方式,先记录下第一种使用事务方式:使用 executeInTransaction 方法。

m0_62645012的博客 1068

【unity实战】随机地下城生成3——设置人物移动脚本、动画的切换和摄像机的跟随(含源码)

给房间添加触发器碰撞体,用来判断角色是否进入房间切割人物图片,注意人物每个图片高度可能不同,所有我们需要把轴心调整到人物的底部把人物跑步图片的高度,统一调成20,下面镂空,达到跳跃的效果快速创造人物动画,以人物idle为例,我们选中所有的idle人物图片,拖拽至窗口,unity就会自动生成,并提示保存动画位置别忘记设置人物排序图层,运行人物就动起来了新增run动画设置人物碰撞体设置刚体将重力设置为0,持续人物移动和动画切换的代码设置摄像机跟随单例代码在room中调用。

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 1052

springboot2.x +kafka使用和源码分析一(自动装配)

序言: 个人感觉springboot的源码是web应用开源框架中写的最好的,观看它的源码可以学习它的编码风格,代码设计思想,如何做到给予使用者最好的使用体验,隐藏连接各应用组件的实现细节,极大降低类开发者实力的要求。查看springboot对各组件的自动装配实现,可以很详细的了解到spring对于组件核心类的初始化过程,以及核心类的作用以及之间的依赖关系。 在使用springboot项目中集成...

F_Hello_World的博客 1802

别白忙活!EAAI投稿避坑指南:5条红线碰就拒,工程应用重点划重点

EAAI投稿避坑指南:5条红线与工程应用要点 投稿《Engineering Applications of Artificial Intelligence》(EAAI)需特别注意5条红线,否则直接拒稿:1)避免提出新隐喻元启发式算法,应聚焦具体工程应用;2)摘要须明确区分AI贡献与工程应用;3)标题和摘要禁止使用未定义缩写;4)必须采用单栏格式;5)关键词不能包含缩写。此外,论文需突出AI方法在工程实践中的创新与落地价值,建议补充实际工程数据、部署成本分析和与传统方法的对比。投稿前务必逐项核查这5条要求,以

ZhangJiqun&191cm&85kg 3194

【CanMV K210】AI 视觉 MNIST 手写数字识别与分类推理

本文介绍了基于CanMV K210开发板的MNIST手写数字识别实验。实验通过摄像头采集图像,经过开窗、灰度化、缩放、反色等预处理后,使用KPU神经网络加速器运行MNIST分类模型,最终在LCD上显示识别结果。重点讲解了分类模型与检测模型的区别、图像预处理流程以及KPU推理结果的解析方法。实验帮助理解从图像采集到分类输出的完整AI视觉处理链路,并提供了调试思路和硬件连接说明。

Mr数据杨 364

springboot2.x +kafka使用和源码分析二(topic配置)

上一章我们了解到KafkaAutoConfiguration自动初始化依赖Bean,如下图所示若应用中不包含kafkaAdmin对象,KafkaAutoConfiguration为我们应用创建一个,那么kafkaAdmin这个类的作用是什么呢? @Bean @ConditionalOnMissingBean public KafkaAdmin kafkaAdmin() {...

F_Hello_World的博客 2005

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Springboot2整合kafka的两种使用方式

Springboot2整合kafkakafkadocker上安装环境Springboot2引入kafka基于注解基于客户端 kafka是一个分布式消息队列。在项目中应用十分广泛,具有高性能、持久化、多副本备份、横向扩展能力。 kafka 在多台机器上分别部署Kafka,即Kafka集群。每台机器运行的Kafka服务称为broker。 一个Topic主题可以被分为若干个分区(partitio...

冲动的仔bb博客 1万+

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

springboot2.x +kafka使用和源码分析九(KafkaListenerEndpointRegistry暂停启动容器)

我们在运行中如果需要暂停启动容器时可以通过此类KafkaListenerEndpointRegistry来处理。 KafkaListenerEndpointRegistry源码(只解释了核心代码): public class KafkaListenerEndpointRegistry implements //当spring销毁bean时执行操作 Dispo...

F_Hello_World的博客 4324

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

SpringBoot整合Kafka与事务使用

一,创建工程项目 第一步,填写项目信息 第二步 项目结构 二、项目的代码 2.1 给出application.properties的代码 server.port=8081 logging.level.root=INFO # 生产者 spring.kafka.producer.bootstrap-servers=192.168.0.183:9092 # 消费者 spring.kafka.consumer.bootstrap-servers=192.168.0.183:9092 .

weixin_39240837的博客 2002

springboot2.x +kafka使用和源码分析五(消费者配置使用)

上一章描述springboot对于kafka事务的支持,本章主要叙说springboot对于consumer支持。 这里通过两种方式 第一种:由springboot框架来初始化基础bean,我们只需要在yml配置文件中编写配置即可。如下图所示(常规配置 具体所有配置可参考http://kafka.apache.org/documentation/的consumer): springbo...

F_Hello_World的博客 1373

springBoot2.x集成kafka

最近在做一个物联网paas项目,实时设备预警结合kafka流式实时计算的特定,采用springBoot结合kafka来完成 kafka环境搭建——kafka基本命令及环境搭建 依赖 <!-- kafka --> <dependency> <groupId>org.springframework.kafka</groupId&...

weixin_44627989的博客 858

springboot 2.6.x 整合 2.8.0kafka

Kafka 本质上是⼀个消息队列。与zeromq不同的是,Kafka是一个独立的框架而不是一个库。这里主要介绍其原理,至于具体的安装等操作不做介绍,只是提示一下,第一次运行时,先设置前台运行,看会不会报错。人生路上遇风雨,才发现,路必须自己走,苦必须自己受;生活路上有苦甜,才发现,伤必须自己舔,槛必须自己过。人生是一种平衡,你拥有了这样,必然会错过那样;你什么都想得到,结果通常会失去更多。不必奢求人生中有绝对的公平,公平就如天平的两端,一端的付出越多,别一端才可以承载更多的希冀。

weixin_45982841的博客 1340

springboot集成整合kafka-kafka事务、生产者事务支持、kafkaTemplate.executeInTransaction

写在前面:各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢! 先看下下面这种情况,程序都出错了,按理说消息也不应该成功 @GetMapping("/send9") public void test9(String message) { kafkaTemplate.send(topic, message); throw new RuntimeException("fail"); } 但是执行结果是

FAIRYTAIL的博客 4721

springboot2.x整合kafka【详细】

一、中间件部署 环境 服务器系统版本:CentOS 7.3.1611 zookeeper使用版本:zookeeper-3.4.14 kafka使用版本:kafka_2.12-2.3.0 版本选择依据 kafka-zookeeper对应版本(最新可参考官网:http://kafka.apache.org/downloads): springboot-kafka客户端对应版本(https://spring.io/projects/spring-kafka): 下载地址(多个镜像仓库可选):https:

weixin_40815218的博客 2050

【SpringBoot 2学习笔记】《十三》SpringBoot2消息之旅,带你体验RabbitMQ和Kafka消息发送

消息队列一般的正常业务开发中基本上不怎么涉猎,都是系统整合或特殊业务场景下才有用武之地。所以大部分程序员在工作中基本没有怎么接触。本章主要内容,就是带领大家入门体验一下消息队列的使用过程,扩展一下知识体系,方便今后有需要时根据实际的业务场景进行定制开发。为了方便,本文中使用的RabbitMQ直接使用了阿里的云服务,这个是按照发送消息的次数计费,比较便宜。Kafka服务的话,阿里云的服务比较贵,就没有再购买服务,自己在原来买的ECS服务器上安装了一下,方便进行程序的开发调试。

黑白猿的琐碎日常 2万+
上一篇: springboot2.x +kafka使用和源码分析三(生产者配置)
下一篇: springboot2.x +kafka使用和源码分析五(消费者配置使用)
F_Hello_World
博客等级 码龄11年 38粉丝 58原创
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值