Redis Sentinel monitors a Redis primary and its replicas, and when the primary stops responding, the Sentinels agree on the failure, promote a replica and tell clients where the new primary is. In this tutorial you will build a three-server Redis setup on Ubuntu 24.04 with one primary, two replicas and a Sentinel on every server, then trigger a failover and connect an application that follows it automatically.

Prerequisites

To follow this tutorial, you need:

  • Three servers running Ubuntu 24.04 LTS, for example three CubePath VPS, connected by a private network. This guide uses these addresses:
HostnamePrivate IPInitial role
redis110.0.0.11Primary + Sentinel
redis210.0.0.12Replica + Sentinel
redis310.0.0.13Replica + Sentinel
  • A non-root user with sudo privileges on each server.
  • UFW enabled on each server, with SSH allowed.

Replace the IP addresses with your own throughout the guide.

How Sentinel decides to fail over

Each Sentinel pings the primary. When a Sentinel gets no valid reply for down-after-milliseconds, it marks the primary as subjectively down (+sdown). When the number of Sentinels that agree reaches the quorum (2 in this guide), the primary is objectively down (+odown). One Sentinel is then elected leader by a majority of all Sentinels, promotes the best replica and reconfigures the others. When the old primary comes back, Sentinel turns it into a replica of the new one.

Step 1 - Installing Redis and Sentinel

Run this step on all three servers. Ubuntu packages Redis server and Sentinel separately:

sudo apt update
sudo apt install redis-server redis-sentinel

Both services start right away with their default configuration. Confirm the versions:

redis-server --version
redis-sentinel --version
Redis server v=7.0.15 sha=00000000:0 malloc=jemalloc-5.3.0 bits=64 build=...
Redis server v=7.0.15 sha=00000000:0 malloc=jemalloc-5.3.0 bits=64 build=...

Step 2 - Opening the firewall on the private network

Redis listens on port 6379 and Sentinel on port 26379. Allow both only from the private subnet, on every server:

sudo ufw allow from 10.0.0.0/24 to any port 6379 proto tcp
sudo ufw allow from 10.0.0.0/24 to any port 26379 proto tcp

Check the rules:

sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
6379/tcp                   ALLOW       10.0.0.0/24
26379/tcp                  ALLOW       10.0.0.0/24

Step 3 - Configuring the Redis primary and replicas

Every node needs the same password in two directives: requirepass protects the node itself, and masterauth lets it authenticate to the primary when it is a replica. Because any node can become primary after a failover, set both on all three servers. Generate a strong password once and reuse it everywhere:

openssl rand -base64 32

On redis1, open the configuration:

sudo nano /etc/redis/redis.conf

Find the existing bind line and add the private IP, then set the password directives (they are commented out by default). Replace your_redis_password with the generated password:

bind 127.0.0.1 -::1 10.0.0.11
requirepass your_redis_password
masterauth your_redis_password

On redis2 and redis3, make the same changes with each server's own IP in bind, and add a replicaof line pointing to the primary:

bind 127.0.0.1 -::1 10.0.0.12
requirepass your_redis_password
masterauth your_redis_password
replicaof 10.0.0.11 6379

Restart Redis on all three servers:

sudo systemctl restart redis-server

To avoid putting the password on the command line, export it in the REDISCLI_AUTH variable, which redis-cli reads automatically:

export REDISCLI_AUTH='your_redis_password'

Check replication from redis1:

redis-cli info replication
# Replication
role:master
connected_slaves:2
slave0:ip=10.0.0.12,port=6379,state=online,offset=420,lag=0
slave1:ip=10.0.0.13,port=6379,state=online,offset=420,lag=0
...

Write a key on the primary and read it on a replica to confirm data flows:

redis-cli set sentinel:test ok
redis-cli -h 10.0.0.12 get sentinel:test
"ok"

Step 4 - Configuring Sentinel

Run this step on all three servers; the Sentinel configuration is identical everywhere. Open the file installed by the package:

sudo nano /etc/redis/sentinel.conf

Find the existing sentinel monitor line and the related mymaster lines, and set them to the following values. Add sentinel auth-pass right after sentinel monitor:

sentinel monitor mymaster 10.0.0.11 6379 2
sentinel auth-pass mymaster your_redis_password
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1

What each line does:

  • sentinel monitor mymaster 10.0.0.11 6379 2: watch the primary at that address under the name mymaster, with a quorum of 2.
  • auth-pass: the password Sentinel uses to talk to the Redis nodes.
  • down-after-milliseconds 5000: consider a node down after 5 seconds without a valid reply. The default is 30 seconds.
  • failover-timeout 60000: time limit for a failover attempt, and the wait before retrying one.
  • parallel-syncs 1: resynchronize replicas with the new primary one at a time, so the others keep serving reads.

Sentinel rewrites this file at runtime to store the discovered replicas, the other Sentinels and the current primary, so the file must stay writable by the redis user. The package already sets the right ownership.

Restart Sentinel on all three servers:

sudo systemctl restart redis-sentinel

Step 5 - Verifying the Sentinel setup

Ask any Sentinel which node is the current primary:

redis-cli -p 26379 sentinel get-master-addr-by-name mymaster
1) "10.0.0.11"
2) "6379"

Check that the Sentinels found each other and can reach the quorum:

redis-cli -p 26379 sentinel ckquorum mymaster
OK 3 usable Sentinels. Quorum and failover authorization can be reached

You can also list what each Sentinel knows with sentinel replicas mymaster and sentinel sentinels mymaster. The Sentinel log confirms the discovery:

sudo tail -n 20 /var/log/redis/redis-sentinel.log
+monitor master mymaster 10.0.0.11 6379 quorum 2
+slave slave 10.0.0.12:6379 10.0.0.12 6379 @ mymaster 10.0.0.11 6379
+slave slave 10.0.0.13:6379 10.0.0.13 6379 @ mymaster 10.0.0.11 6379
+sentinel sentinel 3f1c... 10.0.0.12 26379 @ mymaster 10.0.0.11 6379
+sentinel sentinel 9a7e... 10.0.0.13 26379 @ mymaster 10.0.0.11 6379

Step 6 - Testing automatic failover

Simulate a crash of the primary. On redis1, stop Redis (leave Sentinel running):

sudo systemctl stop redis-server

On redis2, follow the Sentinel log:

sudo tail -f /var/log/redis/redis-sentinel.log

After about five seconds you see the failure detected, agreed and resolved:

+sdown master mymaster 10.0.0.11 6379
+odown master mymaster 10.0.0.11 6379 #quorum 3/2
+try-failover master mymaster 10.0.0.11 6379
+elected-leader master mymaster 10.0.0.11 6379
+selected-slave slave 10.0.0.12:6379 10.0.0.12 6379 @ mymaster 10.0.0.11 6379
+promoted-slave slave 10.0.0.12:6379 10.0.0.12 6379 @ mymaster 10.0.0.11 6379
+switch-master mymaster 10.0.0.11 6379 10.0.0.12 6379

Press Ctrl+C to stop following the log, then confirm the new primary:

redis-cli -p 26379 sentinel get-master-addr-by-name mymaster
1) "10.0.0.12"
2) "6379"

Now bring the old primary back on redis1:

sudo systemctl start redis-server

Within a few seconds Sentinel logs +convert-to-slave and redis1 starts replicating from redis2:

redis-cli info replication | grep -E 'role|master_host|master_link_status'
role:slave
master_host:10.0.0.12
master_link_status:up

For planned maintenance you do not need to stop anything: redis-cli -p 26379 sentinel failover mymaster promotes a replica in a controlled way.

Step 7 - Connecting a client through Sentinel

Applications must not hardcode the primary address. Instead, they ask the Sentinels for it and reconnect after a failover. Most Redis client libraries support this. Here is an example with the Python library on any machine in the private network:

sudo apt install python3-redis
nano sentinel_test.py
from redis.sentinel import Sentinel

PASSWORD = "your_redis_password"

sentinel = Sentinel(
    [("10.0.0.11", 26379), ("10.0.0.12", 26379), ("10.0.0.13", 26379)],
    socket_timeout=0.5,
)

primary = sentinel.master_for("mymaster", socket_timeout=0.5, password=PASSWORD)
replica = sentinel.slave_for("mymaster", socket_timeout=0.5, password=PASSWORD)

print("Primary:", sentinel.discover_master("mymaster"))
primary.set("app:counter", 1)
print("Read from replica:", replica.get("app:counter"))

Run it:

python3 sentinel_test.py
Primary: ('10.0.0.12', 6379)
Read from replica: b'1'

Writes always go to whichever node the Sentinels report as primary, so the application keeps working after the next failover without a configuration change.

Troubleshooting

  • Replicas show master_link_status:down: usually a missing or wrong masterauth, or the primary's bind does not include its private IP. Check sudo tail /var/log/redis/redis-server.log on the replica.
  • sentinel ckquorum reports fewer than 3 Sentinels: port 26379 is blocked between servers, or the Sentinels were started before the primary was reachable. Check UFW, then restart redis-sentinel.
  • Failover never starts (+sdown but no +odown): the other Sentinels still reach the primary, so there is no agreement. This is expected when only one Sentinel has a network problem.
  • Sentinel does not start after editing the file: run sudo journalctl -u redis-sentinel -n 50. A common cause is that sentinel.conf is no longer writable by the redis user; fix it with sudo chown redis:redis /etc/redis/sentinel.conf.

Conclusion

You now have a Redis primary with two replicas and three Sentinels that detect a failed primary, promote a replica in a few seconds and return the old primary to service as a replica. Next, enable persistence (appendonly yes) according to how much data you can afford to lose, point your application's Redis client to the Sentinels instead of a single host, and add monitoring for the +switch-master event so you know when a failover happened. If you need more memory or write throughput than a single primary provides, look at Redis Cluster, which shards data across several primaries.