io.lettuce.core.RedisCommandExecutionException: ERR EXEC without MULTI

在使用redisTemplate的事务功能时,代码运行抛出异常:

java 复制代码
io.lettuce.core.RedisCommandExecutionException: ERR EXEC without MULTI
	at io.lettuce.core.internal.ExceptionFactory.createExecutionException(ExceptionFactory.java:147)
	at io.lettuce.core.internal.ExceptionFactory.createExecutionException(ExceptionFactory.java:116)
	at io.lettuce.core.protocol.AsyncCommand.completeResult(AsyncCommand.java:120)
	at io.lettuce.core.protocol.AsyncCommand.complete(AsyncCommand.java:111)
	at io.lettuce.core.protocol.CommandHandler.complete(CommandHandler.java:747)
	at io.lettuce.core.protocol.CommandHandler.decode(CommandHandler.java:682)
	at io.lettuce.core.protocol.CommandHandler.channelRead(CommandHandler.java:599)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:748)

出现上面这个异常的原因是在执行redis事务时,执行exec命令时没有检查到multi命令;这是因为redis需要所有命令都在一个连接上提交才能判断到命令是否执行,而默认使用连接池提交命令时不能保证所有命令都在一个连接上提交。为了解决这个问题,在springboot中需要在方法上面添加@Transactional注解,并且方法内设置开启事务支持,方法代码如下:

java 复制代码
@Transactional
public void runTransaction() {
    // 开启事务支持
    redisTemplate.setEnableTransactionSupport(true);
    // 表示开启事务
    redisTemplate.multi();

    // 执行多个redis命令
    redisTemplate.opsForValue().set("key1", "value1");
    redisTemplate.opsForValue().set("key2", "value2");
    redisTemplate.opsForValue().set("key3", "value3");

    // 提交执行
    redisTemplate.exec();
    // 取消执行
    // redisTemplate.discard();
    // 关闭事务支持
    redisTemplate.setEnableTransactionSupport(false);
}

上面代码还需要注意事务方法不能在同一个类内部调用,@Transactional 注解需要代理才能生效,否则事务还是不生效,上面的异常依然会抛出。

上面这种处理事务方式不太推荐,在redisTemplate中建议使用SessionCallback实现事务功能。

相关推荐
摇滚侠11 分钟前
JAVA 项目教程《黑马商城-Redis 篇》,分布式架构项目,从开发到部署
java·redis·分布式
zhang2008l16 分钟前
redis连接服务
数据库·redis·bootstrap
中年程序员一枚27 分钟前
spring-cloud-starter-openfeign现实中的运行逻辑
java·spring boot·后端
一个有温度的技术博主1 小时前
Redis系列二:认识Redis
数据库·redis·缓存
码哥字节2 小时前
Redis 8.0~8.4 重要更新,新特性很强!
数据库·redis·缓存
只能是遇见2 小时前
SpringBoot + vue 管理系统
vue.js·spring boot·后端
Jinkxs2 小时前
Java 部署:Jenkins Pipeline 构建 Java 项目(自动化)
java·spring boot
celeste03102 小时前
Redis Summary
linux·运维·服务器·redis·笔记
givemeacar2 小时前
redis 使用
数据库·redis·缓存
a8a3022 小时前
Spring Boot 3.3.4 升级导致 Logback 之前回滚策略配置不兼容问题解决
java·spring boot·logback