Fix the common Spring Redis error: redis err exec without multi. Our Live Support Team is ready to assist.
How to Fix “redis err exec without multi” in Spring Redis
Encountering the redis err exec without multi exception can be puzzling, especially when
multi()
is clearly used in the code. This error often occurs when attempting to use Redis transactions with Spring Data Redis. The stack trace usually points to:
io.lettuce.core.RedisCommandExecutionException: ERR EXEC without MULTI
Copy Code
An Overview
At first glance, the code may appear correct:
redisTemplate.opsForHash().put("customer001", "salary", "5000");
redisTemplate.watch("customer001");
redisTemplate.multi();
redisTemplate.opsForHash().put("customer001", "age", "20");
redisTemplate.exec();
Copy Code
However, despite calling multi()
, Redis responds with redis err exec without multi. The issue lies in how Spring Redis manages connections during transactional operations.
Why This Error Happens
Spring Data Redis disables transaction support by default. Looking into the RedisTemplate source reveals the following:
public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {
private boolean enableTransactionSupport = false;
}
Copy Code
To enable transactions, the following method is often added:
redisTemplate.setEnableTransactionSupport(true);
Copy Code
Updated code:
redisTemplate.opsForHash().put("customer001", "salary", "5000");
redisTemplate.setEnableTransactionSupport(true);
redisTemplate.watch("customer001");
redisTemplate.multi();
redisTemplate.opsForHash().put("customer001", "age", "20");
redisTemplate.exec();
Copy Code
Yet, even after setting enableTransactionSupport
to true
, the same exception can persist.
The Solution: Use SessionCallback
The actual fix requires the use of SessionCallback
. This ensures that all operations, watch
, multi
, and exec
, run on the same Redis connection. Here’s the correct approach:
redisTemplate.execute(new SessionCallback<List<Object>>() {
@Override
public <K, V> List<Object> execute(RedisOperations<K, V> operations) throws DataAccessException {
redisTemplate.opsForHash().put("customer001", "salary", "5000");
redisTemplate.watch("customer001");
redisTemplate.multi();
redisTemplate.opsForHash().put("customer001", "age", "20");
return redisTemplate.exec();
}
});
Copy Code
This resolves the issue effectively by keeping the transaction within a single connection context and avoids issues like redis error socket closed unexpectedly.
[If needed, Our team is available 24/7 for additional assistance.]
Important Note for Redis Cluster Users
The above solution applies to Redis standalone mode only. Redis cluster mode does not support the WATCH
command. In such cases, Lua scripts should be used to maintain atomic operations without relying on transaction commands like watch
or multi
.
Conclusion
The redis err exec without multi error is typically caused by connection inconsistencies or disabled transactional support in Spring Redis. While enabling transaction support may seem like the fix, it’s not enough. Wrapping the logic inside a SessionCallback is the reliable way to ensure proper Redis transaction handling.
0 Comments