How to configure Redis clients when connecting to master-replica setup? - redis

I have a Redis setup with 1 master and 2 replicas - so totally 3 nodes.
Given that writes can happen only via master node while reads can happen via all 3 nodes, how do I configure the clients?
Can I pass all nodes IP in the IP list and the client will take care of connecting to the right node by itself?
Or do the clients need to be configured separately for reads and writes?

It depends on the specific client you are using; some clients automatically split read-only / write commands based on the client-connection configuration, while others allow to specify the preferred replication target at the command or invocation level.
For example, ioredis automatically handles that through the scaleReads configuration option, while StackExchange.Redis allows to handle that through the CommandFlags enum at the command invocation level: you should really check the documentation of the specific Redis client you want to use.
Finally, redis-cli does not split read-only / write commands; it can connect (via the -c option) to a Redis Cluster and follow slot redirections automatically - but the connection will always happen against a master node, with no read/write splitting.

Related

Is there a way to restrict writes to master only in redis?

I have a redis cluster created with master slave mode. I want to create a redisson client to access the cluster but I want to specify separate endpoints for reads and writes. Writes should go to master and reads should happen from the slaves. There is a config readMode that can I set to SLAVE to read only from slave nodes but how do I restrict writes to master only?
In Redis, writes happen only in master nodes. So you don't need separate config to handle that.
There is a config readMode that can I set to SLAVE to read only from slave nodes but how do I restrict writes to master only?
Writes are executed in master nodes.
All commands are executed in the master nodes, by default: while Redis Enterprise allows for a multi-master active-active clusters, Redis (Open Source) only allows one master node and zero or more replicas per slot range. In all cases, all nodes can receive both read and write commands but, by default, replicas reply with a -MOVED redirection error along with the endpoint of the master which is believed to handle a given target key. Clients may use that information to contact the master which will actually execute the command.
With that being said, replicas can be configured to reply to read-only commands - provided they handle the slot range of the given target key. In that context, most cluster-aware Redis clients allow to read from replicas with the goal of distributing the load - with the risk of reading stale data: Redisson manages that through the readMode setting and automatically deals with the aforementioned connection configuration.

Does it require to put load balancer before Redis cluster

I am using Redis Cluster on 3 Linux servers (CentOS 7). I have standard configuration i.e. 6 nodes, 3 master instances, and 3 slave instances (one master have one slave) distributed on these 3 Linux servers. I am using this setup for my web application for data caching, HTTP response caching. My aim is to read primary and write secondary i.e. Read operation should not fail or delayed.
Now I would like to ask is it necessary to configure any load balancer before by 3 Linux servers so that my web application requests to Redis cluster instances can be distributed properly on these Redis servers? Or Redis cluster itself able to handle the load distribution?
If Yes, then please mention any reference link to configure the same. I have checked official documentation Redis Cluster but it does not specify anything regarding load balancer setup.
If you're running Redis in "Cluster Mode" you don't need a load balancer. Your Redis client (assuming it's any good) should contact Redis for a list of which slots are on which nodes when your application starts up. It will hash keys locally (in your application) and send requests directly to the node which owns the slot for that key (which avoids the extra call to Redis which results in a MOVED response).
You should be able to configure your client to do reads on slave and writes on master - or to do both reads and writes on only masters. In addition to configuring your client, if you want to do reads on slaves, check out the READONLY command: https://redis.io/commands/readonly .

Redis Cluster or Replication without proxy

Is it possible to build one master (port 6378) + two slave (read only port: 6379, 6380) "cluster" on one machine and increase the performances (especially reading) and do not use any proxy? Can the site or code connect to master instance and read data from read-only nodes? Or if I use 3 instances of Redis I have to use proxy anyway?
Edit: Seems like slave nodes don't have any data, they try to redirect to master instance, but it is not correct way, am I right?
Definitely. You can code the paths in your app so writes and reads go to different servers. Depending on the programming language that you're using and the Redis client, this may be easier or harder to achieve.
Edit: that said, I'm unsure how you're running a cluster with a single master - the minimum should be 3.
You need to send a READONLY command after connecting to the slave before you could execute any read commands.
A READONLY command only affects during the current socket session which means you need this command for every TCP connection.

Failing over with single Replication Group on ElastiCache Redis

I'm testing out ElastiCache backed by Redis with the following specs:
Using Redis 2.8, with Multi-AZ
Single replication group
1 master node in us-east-1b, 1 slave node in us-east-1c, 1 slave node in us-east-1d
The part of the application writing is directly using the endpoint for the master node (primary-node.use1.cache.amazonaws.com)
The part of the application doing only reads is pointing to a custom endpoint (readonly.redis.mydomain.com) configured in HAProxy, which then points to the two other read slave end points. (readslave1.use1.cache.amazonaws.com and readslave2.use1.cache.amazonaws.com)
Now lets say the primary node (master) fails in us-east-1b.
From what I understand, if the master instance fails, I won't have to change the url for the end point for writing to Redis (primary-node.use1.cache.amazonaws.com), although from there, I still have the following questions:
Do I have to change the endpoint names for the read only slaves?
How long until the missing slave is added into the pool?
If there's anything else I'm missing, I'd appreciate the advice/information.
Thanks!
If you are using ElastiCache, you should make use the "Primary EndpointThe" provided by AWS.
That endpoint actually is backed by Route53, if the primary (master) redis is down, since you enable MutliA-Z, it will auto fail over to one of the read replica (slave).
In that case, you don't need to modify the endpoint of your redis.
I don't know why you have such design, seems you only want write to master, but always read from slave.
For HA Proxy part, you should include TCP check for ALL 3 redis nodes, using their "Read Endpoint"
In haproxy, you can check if the endpoint is SLAVE, if yes, your haproxy should redirect the traffic to that.
Notice that in the application layer, if your redis driver don't support auto reconnect, your script will fail to connect to the new master nodes.
In addition to "auto reconnect", since AWS is using Route53 DNS to do fail over, some lib will NOT do NS lookup again, which means the DNS is still pointing to the OLD ip which is the old master.
Using HAproxy can solve this problem.

Redis DB Master Slave set up

I have installed Redis for my nodeJS application and configured it to be a slave for another instance of Redis DB running on a different server. Can I have the same instance (different DB) of Redis (running as slave) act as Master for locally installed application?
Thanks in advance
Yes, you can, but with a big caveat.
Any slave instance can be master of one or several other instances. So you can imagine daisy chaining slaves and build a hierarchical replication system.
Now, my understanding is you don't need your slave to feed another Redis instance, but just allow an application to perform read/write operations in another database of the slave instance.
To allow it, you need to set the value of the slave-read-only parameter to "no" in the slave configuration:
# You can configure a slave instance to accept writes or not. Writing against
# a slave instance may be useful to store some ephemeral data (because data
# written on a slave will be easily deleted after resync with the master) but
# may also cause problems if clients are writing to it because of a
# misconfiguration.
#
# Since Redis 2.6 by default slaves are read-only.
#
# Note: read only slaves are not designed to be exposed to untrusted clients
# on the internet. It's just a protection layer against misuse of the instance.
# Still a read only slave exports by default all the administrative commands
# such as CONFIG, DEBUG, and so forth. To a limited extend you can improve
# security of read only slaves using 'rename-command' to shadow all the
# administrative / dangerous commands.
slave-read-only no
Now, all the write operations you will run on this instance will be ephemeral. If the link is lost between the master and the slave, the slave will completely synchronize again to the master. All the data you have set on the slave will be lost. If you stop and restart the slave, you will also loose all the ephemeral data.
It may or may not suit your needs.
There is no way to parameter the synchronization (or the persistence options) at the database level. You cannot tell Redis to synchronize a given database, and not another one. Configuration always applies at the instance level.