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实现事务功能。

相关推荐
Amagi.4 分钟前
Redis的内存淘汰策略
数据库·redis·mybatis
无休居士1 小时前
【实践】应用访问Redis突然超时怎么处理?
数据库·redis·缓存
.Net Core 爱好者1 小时前
Redis实践之缓存:设置缓存过期策略
java·redis·缓存·c#·.net
用生命在耍帅ㅤ1 小时前
java spring boot 动态添加 cron(表达式)任务、动态添加停止单个cron任务
java·开发语言·spring boot
程序员-珍2 小时前
SpringBoot v2.6.13 整合 swagger
java·spring boot·后端
徐*红2 小时前
springboot使用minio(8.5.11)
java·spring boot·spring
骆晨学长2 小时前
基于springboot的智慧社区微信小程序
java·数据库·spring boot·后端·微信小程序·小程序
bjzhang752 小时前
SpringBoot开发——整合SpringDoc实现在线接口文档
spring boot·springdoc
Flying_Fish_roe3 小时前
Spring Boot-Session管理问题
java·spring boot·后端
赚钱给孩子买茅台喝3 小时前
智能BI项目第四期
java·spring boot·spring cloud·aigc