Skip to content

Redis Sentinel: How to refresh master client object when master changes on failover? #1500

@Kaushal28

Description

@Kaushal28

Version: redis-py: 3.5.3 and redis: 6.2

Platform: Mac OS Big Sur

Description:

I have setup a Redis replica with one master and two slaves with Redis Sentinel monitoring each of the nodes. I'm using redis-py library to communicate with master and slaves. Here is the code that I use to connect with master and slaves:

from redis.sentinel import Sentinel

sentinel = Sentinel([("localhost", 5000)])  # connect to one of the sentinels
master = sentinel.master_for("mymaster")  # get master object
slave = sentinel.slave_for("mymaster")  # get slave object

Now, I would use master for write and slave for reads. But the problem is that when failover occurs, the master object needs to be refreshed in order to point to a new master. For that, as mentioned in this answer and the docs, I'm supposed to subscribe to +switch-master channel to receive the address of new master.

But the question is that, using which object am I supposed to subscribe to that channel? I tried this using master object as follows:

    ps = master.pubsub()
    ps.subscribe("+switch-master")

And when the master was down, I tried getting the message as following:

ps.get_message()

But this does not return the expected message because the master itself is down I think.

The sentinel object does not support the pubsub.

    >>> sentinel.pubsub()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Sentinel' object has no attribute 'pubsub'

As an alternative, in the linked answer it's suggested to use client-reconfig-script. But how am I supposed to modify an object in my application using an external script?

What am I missing here? I am new to Redis, so any reference would be appreciated.

EDIT

However, if I login into one of the sentinels and then subscribe over the "+switch-master" channel, it receives the message successfully. So How do it do this using redis-py? Is there a way to achieve this currently?

Here is the output from one of the sentinels:

127.0.0.1:5001> SUBSCRIBE +switch-master
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "+switch-master"
3) (integer) 1

1) "message"
2) "+switch-master"
3) "mymaster 127.0.0.1 6379 127.0.0.1 6381"

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions