-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Hi there,
We are experiencing an issue on multi/exec transactions with master/slave configurations (readFrom is set as SLAVE). We are using spring-data-redis and selected lettuce as the redis framework.
Here is the code we wrote to catch the issue
RedisConnection connection= RedisConnectionUtils.getConnection(stringRedisTemplate.getConnectionFactory(), true);
try {
connection.watch(key.getBytes());
connection.multi();
connection.hashCommands().hMSet(key.getBytes(), hash);
connection.exec();
} catch (Exception e) {
} finally {
RedisConnectionUtils.releaseConnection(connection, stringRedisTemplate.getConnectionFactory());
}
We set a master and slave to test it out
hosts:
- 127.0.0.1:6379 (master)
- 127.0.0.1:6380
Then we hit the exception
nested exception is io.lettuce.core.RedisCommandExecutionException: ERR EXEC without MULTI,
And we found the the watch(), multi(), exec() are distributed between the master and slave.
MASTER
[0 127.0.0.1:54159] "WATCH" "xxxx"
[0 127.0.0.1:54159] "HMSET" "xxxx"SLAVE
[0 127.0.0.1:54157] "PING" "NODES"
[0 127.0.0.1:54160] "MULTI"
This could explain why the "ERR EXEC without MULTI" happens. But is this a bug or there is a way to work around? We also tried with stringRedisTemplate.execute(new SessionCallback<Boolean>(){...} but there are no difference.
Right now What I can think about is to have another ConnectionFactory with readFrom -> MASTER, and move all transactional commands to its maintained connections. But this looks like a ugly fix... Please advice.
I also saw a comment in another ticket : "Lettuce connections require single-threaded/synchronized access when using transactions. If two or more threads call concurrently MULTI/EXEC methods this will destroy the connection state. I don't think there is anything we could do here." Wondering the "single-threaded/synchronized" requirement mentioned there is to the RedisConnection or to the shared native connection?
Thanks