Overview

A single Redis instance is a single point of failure. Sentinel provides automatic failover for a primary-replica setup, while Cluster shards data across multiple nodes for horizontal scaling. This tutorial explains when to use each and how to configure them.

Sentinel vs Cluster

AspectSentinelCluster
PurposeHigh availabilityHigh availability + horizontal scaling
Data distributionAll data on every nodeSharded across 16,384 hash slots
Max datasetLimited by single-node RAMScales with node count
ComplexityModerateHigher
Multi-key operationsAlways supportedOnly within the same hash slot
Minimum nodes3 Sentinels + 1 primary + 1 replica6 (3 primaries + 3 replicas)

Part 1: Redis Sentinel

Architecture

Sentinel is a separate process that monitors Redis instances. A quorum of Sentinels must agree that the primary is down before promoting a replica.

         ┌────────────┐
         │ Sentinel 1 │
         └─────┬──────┘
               │ monitors
   ┌───────────┼───────────┐
   ▼           ▼           ▼
┌──────┐   ┌──────┐   ┌──────────┐
│Primary│──▶│Replica│  │ Sentinel 2│
└──────┘   └──────┘   └──────────┘
   ▲
   │
┌──────┐
│Replica│
└──────┘

Primary Configuration

# redis-primary.conf
port 6379
bind 0.0.0.0
requirepass yourpassword
masterauth yourpassword
appendonly yes
save 900 1

Replica Configuration

# redis-replica.conf
port 6379
bind 0.0.0.0
requirepass yourpassword
masterauth yourpassword
replicaof 10.0.0.1 6379
replica-read-only yes

Sentinel Configuration

# sentinel.conf
port 26379
sentinel monitor mymaster 10.0.0.1 6379 2
sentinel auth-pass mymaster yourpassword
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
DirectiveMeaning
sentinel monitorName, host, port, and quorum for the primary
down-after-millisecondsTime before a node is considered down
failover-timeoutMinimum time between failover attempts
parallel-syncsReplicas resyncing simultaneously after failover

Connecting Through Sentinel

from redis.sentinel import Sentinel

sentinel = Sentinel(
    [('sentinel1', 26379), ('sentinel2', 26379), ('sentinel3', 26379)],
    socket_timeout=0.5,
)

master = sentinel.master_for('mymaster', password='yourpassword')
replica = sentinel.slave_for('mymaster', password='yourpassword')

master.set('key', 'value')
print(replica.get('key'))

The client asks Sentinel for the current primary address and reconnects automatically after a failover.

Part 2: Redis Cluster

Hash Slots

Cluster divides the keyspace into 16,384 slots. Each key is mapped with CRC16(key) mod 16384. Every primary owns a range of slots.

Creating a Cluster with Docker

# Create the network
docker network create redis-cluster

# Start six nodes
for port in 7000 7001 7002 7003 7004 7005; do
  mkdir -p ./node-$port
  docker run -d --name redis-$port --net redis-cluster \
    -v $(pwd)/node-$port:/data \
    redis:7-alpine \
    redis-server --port $port \
    --cluster-enabled yes \
    --cluster-config-file nodes.conf \
    --cluster-node-timeout 5000 \
    --appendonly yes \
    --protected-mode no
done

# Get container IPs and create the cluster
docker exec -it redis-7000 redis-cli --cluster create \
  $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' redis-7000):7000 \
  $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' redis-7001):7001 \
  $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' redis-7002):7002 \
  $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' redis-7003):7003 \
  $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' redis-7004):7004 \
  $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' redis-7005):7005 \
  --cluster-replicas 1

Cluster Commands

# Check cluster state
redis-cli -c -p 7000 cluster info
redis-cli -c -p 7000 cluster nodes

# Which node holds a key
redis-cli -c -p 7000 cluster keyslot user:1001

# Reshard slots
redis-cli --cluster reshard 172.20.0.2:7000

# Add a new node
redis-cli --cluster add-node 172.20.0.10:7006 172.20.0.2:7000

# Rebalance slots across nodes
redis-cli --cluster rebalance 172.20.0.2:7000

Cluster-Aware Clients

from redis.cluster import RedisCluster, ClusterNode

nodes = [
    ClusterNode('10.0.0.1', 7000),
    ClusterNode('10.0.0.2', 7000),
    ClusterNode('10.0.0.3', 7000),
]

rc = RedisCluster(startup_nodes=nodes, decode_responses=True)
rc.set('user:1001', 'Alice')
print(rc.get('user:1001'))

Hash Tags for Multi-Key Operations

Multi-key operations require all keys to be in the same slot. Use hash tags to force this:

# Different slots — MGET fails in cluster mode
MGET user:1001:name user:1002:name

# Same slot because the tag between {} is hashed
MGET user:{1001}:name user:{1001}:email

Client-Side Considerations

FeatureSentinelCluster
Pipelines across keysSupportedOnly same-slot keys
Transactions (MULTI/EXEC)SupportedOnly same-slot keys
Lua scriptsSupportedOnly same-slot keys
Pub/SubCluster-wideBroadcast across nodes
FailoverSentinel promotes replicaCluster promotes replica automatically

Operational Best Practices

  • Run at least three Sentinel instances across separate failure domains.
  • Set min-replicas-to-write 1 and min-replicas-max-lag 10 to avoid writing to an isolated primary.
  • Use an odd number of primaries in a Cluster (3, 5) to maintain quorum.
  • Monitor replication lag; alert when it exceeds your tolerance.
  • Enable AOF persistence for durability in addition to RDB snapshots.
  • Test failover regularly in staging. An untested failover path is not a reliable one.

Common Pitfalls

PitfallResultFix
Even number of SentinelsSplit-brain during quorum votingAlways use an odd count
All Sentinels on one hostHost failure takes down monitoringDistribute across zones
Cluster without replicasData loss on primary failureRun at least one replica per primary
Keys not hash-taggedMulti-key operations failUse {tag} in key names