-
Notifications
You must be signed in to change notification settings - Fork 986
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MULTI is dispatched to slave nodes using SLAVE readFrom #779
Comments
There are two issues here: The first one is that The second issue is that when using transactions and Master/Slave with non-master reads, you are likely to experience issues because there is no distributed transaction support. Read-only commands are sent to slaves and write commands hit the master. Consider the following sequence of commands:
In this case, all commands except |
Hi @mp911de Thank you for the explanations, it's very helpful. As you mentioned "Read-only commands are sent to slaves and write commands hit the master." Does it mean if the readFrom set as MASTER, this might work? Or we still need to guarantee the single-thread/synchronized when handling the connection? If you don't mind, could you please help explain how the LettuceConnection works with the native connection to redis node? I saw multiple LettuceConnection could share the native connection, When you say to do the "single-thread/synchronized" on each connection, did you mean LettuceConnection which fetched from ConnectionFactory, or the native single-thread connection? I saw there is a setting We could try to create a separate connection directly to the master node. But since Lettuce already handles well on the auto failover of master-slaves, is there a way we could get the current master ip/port or connection info from ConnectionFactory (or another component)? Thanks |
Yes, this will work
Using transactions and/or blocking commands (
That's a specific implementation of Spring Data Redis. Spring Data takes care of the hairy bits for you meaning, that transactions, pipelining, and blocking commands get issued on dedicated connections.
If you want to use Master/Slave with slave reads, then spin up another Does this make sense? |
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue. |
@mp911de We're facing the same issue OP brought up. We were using Jedis up until now when we realized we were not utilizing the two slaves our (single) Master has connected to. So to improve the utilization, we switched to Lettuce client and it's been working great except for this one use-case where we want to batch a few writes and deletes inside a transaction. So the upshot of this discussion is, if we want to execute transactions on a master-slave deployment, use a separate instance of Also, a couple of more related questions -
|
@asgs to answer your questions:
Happy to continue the discussion on this issue. Another idea came to my mind: Since transactions are broken as soon non-master nodes are touched, we could state, that transactions work only on masters. This assumption can help us to get transactions working with Master/Slave in the sense that we bind transactions to the master node. As soon as Does this make sense? |
@mp911de thank you! we're on the same page. yes, we plan to use only one connection in either mode (transactional and non-transactional). |
Please make sure, when you use transactions to not share the same connection across multiple threads (use pooling in such case). Otherwise, you will run into race conditions. You can share a single connection if you're not using transactional commands. |
@mp911de, when we create the Does Lettuce and/or Spring Data Redis print the Redis connection Id? I could see
|
No, Spring Data Redis does not report a connection Id. The ChannelId you see is a netty-internal id, the chid is the Id of the Happy to improve correlation any further, but let's take this into a new ticket if you feel there is something we can actually do. |
SLAVE
readFromMULTI is no longer considered a read-only command to prevent accidental dispatch to slave nodes.
MULTI is no longer considered a read-only command to prevent accidental dispatch to slave nodes.
MULTI is no longer considered a read-only command to prevent accidental dispatch to slave nodes.
MULTI is no longer considered a read-only command to prevent accidental dispatch to slave nodes.
That's fixed now, we no longer consider |
See #800 for binding transactions in master/slave to the master node. |
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
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.
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
The text was updated successfully, but these errors were encountered: