Search code examples
pythonredisreplication

How to initialize Redis client to write to master and read from slaves


Supposing I have a replicated master-slave Redis setup, how do I actually access it from a client library? Presumably I need a client instance per each host and I need to decide which I want to use for writing and reading, like:

master = redis.Redis(master_host, port)
clients = [redis.Redis(host, port) for host in slave_hosts]

master.set('key', 'value')
client = random.choice(clients)
client.get('other-key')

I was thinking there should be some magic in the library where I could provide a list of hosts for making such routing automatic, but couldn't find it.

I've also looked into redis-cluster and redis-sentinel and they all start by talking about automatic failovers when slaves become masters, and I'm not sure it's what I need. What I need is a consistent master which I can afford to lose for some time (I can hold up updates in a queue).


Solution

  • Are you intentionally splitting reads and writes, and doing so because you already know you will be overwhelming the Redis instance? If not, don't worry about splitting r/w between servers. Use Sentinel from the client as a lookup to see what node is the master and connect to it to do all of your reads and writes.

    Who you do eventually have to split reads off your code will need to written such that you establish a connection for each read-slave and only send reads to it. You'll need to detect failovers to redistribute your r/w split.

    Now if you have a separate read-only process, you can either let it query sentinel for slave in place of master, or you can set up a non-promotable slave to use for that process - though if it goes down you'd lose your access.

    You Aint Gonna Need It (YAGNI) is a good principle to follow here, as is avoiding premature optimization. A single Redis instance can be incredibly fast and doesn't suffer the same performance drops due to highly complex queries you find in traditional SQL datastore. So I would recommend that absent data you run with a standard setup where you simply query sentinel for current master and use the one it returns.