-
Notifications
You must be signed in to change notification settings - Fork 351
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
How frequent lib checks the cluster so as to identify possible changes #571
Comments
Once, you send a command to Redis, and it finds that the connection is broke, the lib will try to get the latest master nodes from the cluster, and connect to it.
If you use Redis Sentinel or Redis Cluster, you can configure which role, master or slave, do you want to connect to. If you use slave mode, the lib will randomly pick one node, and send command to it. If the connection is broken, the lib randomly pick another one, maybe the same one, maybe not. Anyway, it ensures all connections in the connection pool connect to the same node. If you want to distribute the reads among multiple nodes, you have to create multiple Redis instances. If you are working on a backend service application, normally, you have multiple instances of your service application, so the connections should be distributed on multiple nodes. Regards |
Hi, may I have a question connecting to this conversation? you wrote: "Once, you send a command to Redis, and it finds that the connection is broke, the lib will try to get the latest master nodes from the cluster, and connect to it." Does it mean that after the connection reestablishment attempt fails, the library sends CLUSTER SLOTS request to update its inner mapping table? From wireshark traces about a VM restart/reset use case I see that the library detects connection failure in an active connection after 52 second (9 TCP retransmissions) after that there is a reconnection attempt (configurable duration - connect_timeout), and after that CLUSTER SLOTS is sent (2 times, and no more CLUSTER SLOTS request). Does the "52 sec" interval configurable somehow? I see two candidates in connection.h, socket_timeout and keep_alive_s. Is it normal that CLUSTER SLOTS is not sent by the library after the connection is established with the new master (that is, CLUSTER SLOTS are sent on demand)? Thanks in advace, |
NO. It means once the lib finds that the connection is broken, it reconnects to Redis Cluster, and if it successfully connects to it, the client sends a CLUSTER SLOTS request to update local mapping. When the lib finds the connection is broken? Take the following scenario for example: client fetches a connection from connection pool and sends a command to Redis. However, it fails with the connection broken. Client returns the connection to connection pool. Client fetches the broken connection from the pool, checks the connection status, and finds it's broken.
NO, there's no such configuration.
Once the client finds that the connection is broken, it reconnects and updates its mappings. There're cases that it might not do update immediately. For example, also there's a broken connection in the pool, However, when the client tries to fetch a connection, it does not get the broken one. By the way, I might add a worker thread to update the mapping from time to time, so that it might update the mapping more quickly. Regards |
Hello, You are using the terms "library" and "client". What is the difference between them? If I understood well your explanation both refer to redis-plus-plus code, and not the application that uses / calls the redis-plus-plus methods. Note: if you would like to reproduce the scenario then you can apply e.g. the following:
Expected result: new master is elected, traffic is redirected to that master Br, Jozsef |
Yes |
Hello, I would propose the following enhancements (draft algorithm), please consider if it is feasible:
There are applications where 52 sec delay in responses are unacceptable. Certainly, redis-plus-plus user code can be also enhanced to detect this situation and implement the workaround but it would be more elegant solution to implement this in the library. Br, Jozsef |
I'm using Redis Cluster and I would like to distribute the read operations among masters AND their replicas (in other words, I would like to offload the masters from getting all the traffic). Is it possible somehow to instruct library to distribute read commands based e.g. on a ratio? Because as I see, replicas don't get traffic so they are underutilized, as masters undertake all the workload. Thanks |
@georgasa Yes, there was a plan to support customized strategies for choosing between Redis nodes. Before that feature is implemented, you have to do it manually by creating one or more Redis instances that connecting to slave nodes for reading, while creating a Redis instance connecting to master node for writing. Regards |
@jzkiss With #595 fix, redis-plus-plus updates the slot-node mapping every ClusterOptions::slot_map_refresh_interval (by default, it updates every 10 seconds). You can control the update frequency by this parameter:
|
Hello @sewenew, thank you very much for the fix and sorry for the late answer! I have executed two tests: I. Graceful kill of a Redis master instance These are valid use cases in our deployment, we are using redis modules, and when a new corerction in a module added, in kubernetes we are using rolling upgrades of redis pods (to provide in service operations). I. Graceful kill of a Redis master instance - this is Ok with this version. Test setup: During the test one redis master is killed, redispp notices it as FIN is received in the TCP stream and RST for the new connection establishment requests. When redispp recognizes from CLUSTER SLOTS the change in mastership, it connects to new master and uses that channel for data transfer. The existing stream channel towards the other redis master is not broken, it is used throughout the whole test. II. TCP Cut of a Redis master instance In this case I expect that redispp:
But, what is really happening is the following:
It seems the blocking TCP connection to a master is somehow blocks the usage of the connections on the working streams within redispp. I added the recognized exceptions to the figures, maybe it helps to investigate the issue. We still use the earlier version of redispp, because we have a workaround in application level: when 4 sec timeout is detected then the application reinitializes the redispp. This workaround does not work with the new redispp (it crashes after some seconds after the reinitializations). With the workaround we lost 219 transactions, with the new version (and without the workaround) we lost 1707 (traffic was 250 transactions per second). Unfortunately I cannot send you the wireshark traces / logs because they contain sensitive data, but please feel free to ask me if something is not clear from the figures. From TCP traces level, this is the difference: Note: Br, Jozsef |
@jzkiss Sorry for the late reply, and thank you for your detailed info. Please help to clarify a few questions:
Do you mean that the new master has already been elected? Or this happens during the election? Looks like that redis-plus-plus continuously gets moved error or io error, otherwise, it won't continuously send CLUSTER SLOTS command.
This is strange. If the cluster is healthy, i.e. new master elected, and redis-plus-plus connects to new master successfully, it should not continuously send cluster slots command. Does 3208 is the new master? or some other node. It's unclear which one or all of these Redis nodes returns timeout error. NOTE: by default, Redis Cluster is configured as cluster-require-full-coverage yes. In this case, if some node is down, and the new master is not elected, Redis Cluster won't allow new commands. I'm not sure, if that's why redis-plus-plus closed the connection.
Is the crash caused by redis-plus-plus? In that case, if you can give a minimum code snippets that can reproduce the problem, I can do some debugging. Also, is there any easy way to simulate the tcp cut case? I'm not familiar with network configuration, and cannot reproduce the problem. Thanks again! Regards |
Hello @sewenew , thank you for checking the issue. I try to answer to your questions below. Br, Jozsef
The new master was already elected. This is the CLUSTER SLOTS response for the first inquiry: *2 Slot 0-5460 is served by only 172.17.0.3:6383 (new master), the other two slot ranges are served by master / slave.
Based on the slot information that is calculated from the keys all of the masters affected.
These are the relevant settings in the test setup:
I try to reproduce core file and look into it with gdb, but it requires time. I think I met similar situation that #578
_#!/bin/bash REDIS_PORT=$1 echo "iptables -A OUTPUT -p tcp --sport ${REDIS_PORT} -s 172.17.0.3 -j DROP" sleep 2 echo "kill -9 ${REDIS_PID}" In my test ${REDIS_PORT} is 6380 |
Hello, We face the same issue in our client implementation. We are also using an AsyncRedisCluster object and send commands using redis modules. The cluster is using three master/slave nodes. In case it helps, I would like to mention that in our case the problem mainly appears if we ungratefully kill the node in which the library initial connection was established. |
@jzkiss I tried your setup with the script you given, however, I cannot reproduce your problem. Please check the following steps:
The following is the output of the test code:
As you can see from the message, when the node (port 30003) is cut off, commands sent to the node got timeout exception, which is the expected behavior, since after some tcp retransmission, it got the timeout error. However, other 2 nodes (port 30001 and port 30002) does not affected by this operation (commands on key b and c get reply and the callback runs).
I did not observed this behavior. The master nodes that do not affected by the cut off node.
I'll try to reproduce this problem. Regards |
Hi,
I'm wondering how fast the lib will understand that a master-slave failover occurred so as to redirect the write commands to the new master?
Also during sunny days (normal conditions), does the lib distribute the read commands among master AND replicas or it accesses solely the master nodes for every read operation?
Thanks a lot,
Apostolos
The text was updated successfully, but these errors were encountered: