0

My objective is to apply transaction logic (watch+multi) to a redis cluster. I can see here, here and on spring-data-redis repo that transactions on clusters are not supported on spring data redis. Nevertheless, considering that I need to do it on the same node, I have tried to do something like this:

val keySerialized = "myKey".toByteArray()
val valueSerialized = "myValue".toByteArray()

val node = redisTemplate.connectionFactory.clusterConnection.clusterGetNodeForKey(keySerialized)
    
val clusterExecutor = (redisTemplate.connectionFactory.clusterConnection as LettuceClusterConnection).clusterCommandExecutor

clusterExecutor.executeCommandOnSingleNode(
    (ClusterCommandExecutor.ClusterCommandCallback { client: RedisCommands<ByteArray, ByteArray> -> client.watch(keySerialized) })
                ,node)

clusterExecutor.executeCommandOnSingleNode(
    (ClusterCommandExecutor.ClusterCommandCallback { client: RedisCommands<ByteArray, ByteArray> -> client.multi() })
                ,node)

clusterExecutor.executeCommandOnSingleNode(
    (ClusterCommandExecutor.ClusterCommandCallback { client: RedisCommands<ByteArray, ByteArray> -> client.get(keySerialized) })
                ,node)

clusterExecutor.executeCommandOnSingleNode(
    (ClusterCommandExecutor.ClusterCommandCallback { client: RedisCommands<ByteArray, ByteArray> -> client.set(keySerialized, valueSerialized) })
                ,node)

clusterExecutor.executeCommandOnSingleNode(
    (ClusterCommandExecutor.ClusterCommandCallback { client: RedisCommands<ByteArray, ByteArray> -> client.exec() })
                ,node)

This works fine when I'm running just one instance of the code. Example: If I do a SET in the redis console while debugging the code, the transaction will fail as expected.

However, If I am running this code in two threads, what happens is that both are using the same connection. When the second thread runs the MULTI command, the following error is raised

Caused by: io.lettuce.core.RedisCommandExecutionException: ERR MULTI calls can not be nested

I believe that by forcing the executor to use a new connection could be a solution, but I don't know how to do it. Any thoughs on this?

Francisco Cruz
  • 314
  • 3
  • 13

0 Answers0