springboot使用kafka事务的示例代码

 更新时间:2024年06月14日 09:38:31   作者:​​​​​​​ 五敷有你  
Kafka 同数据库一样支持事务,当发生异常的时候可以进行回滚,确保消息监听器不会接收到一些错误的或者不需要的消息,本文就来介绍一下springboot使用kafka事务的示例代码,具有一定的参考价值,感兴趣的可以了解一下

先看下下面这种情况,程序都出错了,按理说消息也不应该成功

@GetMapping("/send")
public void test9(String message) {
    kafkaTemplate.send(topic, message);
    throw new RuntimeException("fail");
}

但是执行结果是发生了异常并且消息发送成功了:

Kafka 同数据库一样支持事务,当发生异常的时候可以进行回滚,确保消息监听器不会接收到一些错误的或者不需要的消息。

kafka事务属性是指一系列的生产者生产消息和消费者提交偏移量的操作在一个事务,或者说是是一个原子操作),同时成功或者失败。使用事务也很简单,需要先开启事务支持,然后再使用。

如何开启事务

如果使用默认配置只需要在yml添加spring.kafka.producer.transaction-id-prefix配置来开启事务,之前没有使用默认的配置,自定义的kafkaTemplate,那么需要在ProducerFactory中设置事务Id前缀开启事务并将KafkaTransactionManager注入到spring中,看下KafkaProducerConfig完整代码:

@Configuration
@EnableKafka
public class KafkaProducerConfig {
@Value("${kafka.producer.servers}")
private String servers;
@Value("${kafka.producer.retries}")
private int retries;
 
public Map<String,Object> producerConfigs(){
    Map<String,Object> props = new HashMap<>();
    props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, servers);
    props.put(ProducerConfig.RETRIES_CONFIG,retries);
    props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
    props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
    // 配置分区策略
    props.put(ProducerConfig.PARTITIONER_CLASS_CONFIG,"com.example.springbootkafka.config.CustomizePartitioner");
    // 配置生产者拦截器
    props.put(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG,"com.example.springbootkafka.interceptor.CustomProducerInterceptor");
    // 配置拦截器消息处理类
    SendMessageInterceptorUtil sendMessageInterceptorUtil = new SendMessageInterceptorUtil();
    props.put("interceptorUtil",sendMessageInterceptorUtil);
    return props;
}
 
@Bean
public ProducerFactory<String,String> producerFactory(){
    DefaultKafkaProducerFactory producerFactory = new DefaultKafkaProducerFactory(producerConfigs());
    //设置事务Id前缀 开启事务
    producerFactory.setTransactionIdPrefix("tx-");
    return producerFactory;
}
 
@Bean
public KafkaTemplate<String,String> kafkaTemplate(){
    return new KafkaTemplate<>(producerFactory());
}
 
@Bean
public KafkaTransactionManager<Integer, String> kafkaTransactionManager(ProducerFactory<String, String> producerFactory) {
    return new KafkaTransactionManager(producerFactory);
}
} 

配置开启事务后,使用大体有两种方式,先记录下第一种使用事务方式:使用 executeInTransaction 方法

直接看下代码:

@GetMapping("/send11")
public void test11(String message) {
    kafkaTemplate.executeInTransaction(operations ->{
        operations.send(topic,message);
        throw new RuntimeException("fail");
    });
}

当然你可以这么写:

@GetMapping("/send11")
public void test11(String message) {
    kafkaTemplate.executeInTransaction(new KafkaOperations.OperationsCallback(){
        @Override
        public Object doInOperations(KafkaOperations operations) {
            operations.send(topic,message);
            throw new RuntimeException("fail");
        }
    });
}

启动项目,访问http://localhost:8080/send10?message=test10 结果如下:

如上:消费者没打印消息,说明消息没发送成功,并且前面会报错org.apache.kafka.common.KafkaException: Failing batch since transaction was aborted 的错误,说明事务生效了。

第一种使用事务方式:使用 @Transactional 注解方式 直接在方法上加上@Transactional注解即可,看下代码:

@GetMapping("/send12")
@Transactional
public void test12(String message) {
    kafkaTemplate.send(topic, message);
    throw new RuntimeException("fail");
}

如果开启的事务,则后续发送消息必须使用@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

到此这篇关于springboot使用kafka事务的文章就介绍到这了,更多相关springboot kafka事务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java8 LocalDateTime极简时间日期操作小结

    Java8 LocalDateTime极简时间日期操作小结

    这篇文章主要介绍了Java8-LocalDateTime极简时间日期操作整理,通过实例代码给大家介绍了java8 LocalDateTime 格式化问题,需要的朋友可以参考下
    2020-04-04
  • Java中的WebSocket与实时通信详解

    Java中的WebSocket与实时通信详解

    本文介绍WebSocket的概念、工作原理及Java中实现WebSocket的技术手段,包括JavaAPIforWebSocket(JSR356)和SpringWebSocket,通过实际应用场景(如即时聊天、实时通知、在线游戏)进行了详细分析,展示了WebSocket在现代Web应用中的重要性,感兴趣的朋友跟随小编一起看看吧
    2025-11-11
  • django 递归查询评论的示例详解

    django 递归查询评论的示例详解

    文章介绍了将表数据转换为树状结构以及如何处理扁平化数据的方法,探讨了在数据管理中的应用和实现技术,感兴趣的朋友一起看看吧
    2025-01-01
  • 基于java socket实现 聊天小程序

    基于java socket实现 聊天小程序

    这篇文章主要介绍了基于java socket实现 聊天小程序,代码分为服务器和客户端,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-12-12
  • Java基础教程之static五大应用场景

    Java基础教程之static五大应用场景

    这篇文章主要给大家介绍了关于Java基础教程之static五大应用场景的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06
  • Idea配置Maven阿里云镜像加速的实现

    Idea配置Maven阿里云镜像加速的实现

    这篇文章主要介绍了Idea配置Maven阿里云镜像加速的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Java 生成任意长度的验证码过程解析

    Java 生成任意长度的验证码过程解析

    这篇文章主要介绍了Java 生成任意长度的验证码过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • IDEA Error:java: 无效的源发行版: 17错误

    IDEA Error:java: 无效的源发行版: 17错误

    本文主要介绍了IDEA Error:java: 无效的源发行版: 17错误,这个错误是因为您的IDEA编译器不支持Java 17版本,您需要更新您的IDEA编译器或者将您的Java版本降级到IDEA支持的版本,本文就来详细的介绍一下
    2023-08-08
  • Springboot - Fat Jar示例详解

    Springboot - Fat Jar示例详解

    这篇文章主要介绍了Springboot - Fat Jar详解,Spring Boot内嵌容器,通过java -jar命令便可以直接启动应用,今天带着大家探索FAT JAR启动的背后原理,需要的朋友可以参考下
    2023-02-02
  • Spring Boot应用监控的实战教程

    Spring Boot应用监控的实战教程

    Spring Boot 提供运行时的应用监控和管理功能,下面这篇文章主要给大家介绍了关于Spring Boot应用监控的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧
    2018-05-05

最新评论