Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I load balance reads on a master/slave redis setup?

I am learning StackExchange.Redis, and Kubernetes, so I made a simple .net core app that reads a key/value from a Redis master+2slaves deployed on kubernetes. (so, everything, Redis and my app, run inside containers)

To connect to redis I use the syntax suggested in the doc:

ConnectionMultiplexer.Connect("server1:6379,server2:6379,server3:6379");

However, if I monitor the 3 containers with redis-cli MONITOR, the requests are processed always from the master, the 2 slaves do nothing, so there is no load balancing.

I have tried also to connect to a Kubernetes load balancer service which exposes the 3 Redis containers endpoints, the result is that when I start the .net app the request is processed randomly by one of the 3 Redis nodes, but then always on the same node. I have to restart the .net app and it will query another node but subsequent queries go always on that node.

What is the proper way to read key/values in a load balanced way using StackExchange.Redis with a master/slave Redis setup?

Thank you

like image 800
Anton M Avatar asked Oct 22 '18 18:10

Anton M


People also ask

How does master-slave work in Redis?

The Redis replication uses an asynchronous method to transfer data from master to slave. The slave periodically acknowledges the received data sent by the master node, and also the master node can have many slaves. Redis can support cascading replication, so the slave can be connected to another slave.

Does Redis cluster have Load Balancer?

Redis load balancing environment Redis Sentinel checks the state of all Redis nodes and changes the role of the Redis server once an error is detected. The load balancer checks the state as well, but it does it periodically every some seconds.

What is master-slave architecture in Redis?

Master-slave architecture for data replication. Redis follows a master-slave approach for replication. One of the servers is a master, and the other servers are called slaves. The slaves are connected to the master. All the writes happen to the master and then the master, sends these changes to the slaves.

What if Redis master goes down?

When a master goes down in a Redis cluster, Redis will wait for node timeout to promote slave to master. There may be additional time taken for slave promotion to master. During the time master goes down to slave promotion to master, writes/reads, especially writes will fail.


2 Answers

SE.Redis has a CommandFlags parameter that is optional on every command. There are some useful and relevant options here:

  • DemandPrimary
  • PreferPrimary
  • DemandReplica
  • PreferReplica

The default behaviour is PreferPrimary; write operations bump that to DemandPrimary, and there are a very few commands that actively prefer replicas (keyspace iteration, etc).

So: if you aren't specifying CommandFlags, then right now you're probably using the default: PreferPrimary. Assuming a primary exists and is reachable, then: it will use the primary. And there can only be one primary, so: it'll use one server.

A cheap option for today would be to add PreferReplica as a CommandFlags option on your high-volume read operations. This will push the work to the replicas if they can be resolved - or if no replicas can be found: the primary. Since there can be multiple replicas, it applies a basic rotation-based load-balancing scheme, and you should start to see load on multiple replicas.

If you want to spread load over all nodes including primaries and replicas... then I'll need to add new code for that. So if you want that, please log it as an issue on the github repo.

like image 80
Marc Gravell Avatar answered Nov 10 '22 19:11

Marc Gravell


As per the docs it should automatically detect master/slaves. It may be that StackExchange.Redis is detecting that all your nodes are masters, thus just selecting one using its own tiebreaker rules.

I would also check the request logs on your redis-pods if there are some invalid commands that are being sent by StackExchange.Redis, maybe you don't have the right permissions for it to detect master/slaves.

Maybe you also have Sentinel enabled and StackExchange doesn't support sentinel

If you see something is not working you can open an issue on Github

Finally, you could also try twemproxy.

like image 38
Rico Avatar answered Nov 10 '22 19:11

Rico