Redis Cluster Configuration
Redis Cluster provides distributed data storage and automatic sharding across multiple nodes without requiring external clustering solutions. It enables horizontal scaling by partitioning data using consistent hashing (hash slots), provides automatic failover with replica nodes, and maintains availability when failures occur. This comprehensive guide covers cluster creation, hash slot management, node operations, replication, resharding, failover mechanisms, and best practices for production Redis Cluster deployments.
Table of Contents
- Architecture and Sharding
- Installation and Prerequisites
- Cluster Initialization
- Hash Slot Management
- Replication and Failover
- Dynamic Resharding
- Cluster Monitoring
- Client Connection
- Maintenance Operations
- Troubleshooting
- Conclusion
Architecture and Sharding
Redis Cluster distributes data across multiple nodes using 16,384 hash slots. Each key is mapped to a slot using CRC16 hashing, and each cluster node manages a range of slots. Clients connect to any node and are redirected to the correct node handling their key. This architecture enables linear scaling by adding nodes and automatic rebalancing of slots.
Cluster nodes communicate through a gossip protocol maintaining cluster topology information. Each node can have replica nodes that copy its data, providing redundancy and enabling failover when a primary node becomes unavailable. The cluster remains operational as long as all hash slots are covered by at least one reachable node.
Installation and Prerequisites
Install Redis with cluster support. Build from source or use repositories:
# Ubuntu/Debian
sudo apt-get install -y redis-server redis-tools
# CentOS/RHEL
sudo dnf install -y redis
# Build from source for latest
cd /tmp
wget http://download.redis.io/redis-stable.tar.gz
tar -xzf redis-stable.tar.gz
cd redis-stable
make
sudo make install PREFIX=/usr/local
# Verify cluster support
redis-server --version
redis-cli --help | grep -i cluster
Create cluster node directories:
# Create user
sudo useradd -r -s /bin/false redis 2>/dev/null || true
# Create data directories for 6 nodes (3 primary + 3 replicas)
for i in {7000..7005}; do
sudo mkdir -p /var/lib/redis-cluster/$i
sudo chown -R redis:redis /var/lib/redis-cluster/$i
sudo chmod 755 /var/lib/redis-cluster/$i
done
# Create configuration directory
sudo mkdir -p /etc/redis-cluster
Cluster Initialization
Create configuration files for each cluster node:
# Create configuration for node 7000
sudo nano /etc/redis-cluster/redis-7000.conf
Add configuration:
# Cluster node configuration
port 7000
bind 0.0.0.0
cluster-enabled yes
cluster-config-file /var/lib/redis-cluster/7000/nodes.conf
cluster-node-timeout 15000
# Data directory
dir /var/lib/redis-cluster/7000
# Logging
logfile /var/log/redis/redis-7000.log
loglevel notice
# Database
databases 16
save 900 1
save 300 10
save 60 10000
# Memory
maxmemory 1gb
maxmemory-policy allkeys-lru
# RDB snapshot
rdbcompression yes
rdbchecksum yes
# AOF
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
# Cluster replication
min-replicas-to-write 1
min-replicas-max-lag 10
# Performance
tcp-backlog 511
timeout 0
tcp-keepalive 300
Create configurations for remaining nodes:
# Create nodes 7001-7005 with modified port and paths
for i in {7001..7005}; do
sudo sed "s/7000/$i/g" /etc/redis-cluster/redis-7000.conf > \
/etc/redis-cluster/redis-$i.conf
done
# Set permissions
sudo chown redis:redis /etc/redis-cluster/redis-*.conf
sudo chmod 600 /etc/redis-cluster/redis-*.conf
Create systemd service template:
sudo nano /etc/systemd/system/[email protected]
Add:
[Unit]
Description=Redis Cluster Node %i
After=network.target
[Service]
Type=simple
User=redis
Group=redis
ExecStart=/usr/local/bin/redis-server /etc/redis-cluster/redis-%i.conf
ExecStop=/bin/kill -TERM $MAINPID
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
Enable and start all cluster nodes:
# Enable services
for i in {7000..7005}; do
sudo systemctl daemon-reload
sudo systemctl enable redis-cluster@$i
done
# Start all nodes
for i in {7000..7005}; do
sudo systemctl start redis-cluster@$i
done
# Verify nodes are running
redis-cli -p 7000 ping
redis-cli -p 7005 ping
Create the cluster using redis-cli:
# Create cluster with 3 primary and 3 replica nodes
redis-cli --cluster create \
192.168.1.10:7000 192.168.1.10:7001 192.168.1.10:7002 \
192.168.1.10:7003 192.168.1.10:7004 192.168.1.10:7005 \
--cluster-replicas 1 \
--cluster-yes
# Verify cluster creation
redis-cli -c -p 7000 CLUSTER INFO
# Get cluster nodes
redis-cli -c -p 7000 CLUSTER NODES
Hash Slot Management
Understand hash slot distribution:
# Check cluster slots
redis-cli -c -p 7000 CLUSTER SLOTS
# Get key slot
redis-cli -c -p 7000 CLUSTER KEYSLOT mykey
# Analyze slot distribution
redis-cli -c -p 7000 CLUSTER NODES | grep -E 'slot|myself'
# View detailed slot info
redis-cli --cluster info 192.168.1.10:7000
Monitor slot ownership:
#!/bin/bash
# Show slot distribution across nodes
redis-cli -c -p 7000 CLUSTER NODES | \
while read line; do
if [[ ! $line =~ ^# ]]; then
id=$(echo $line | cut -d' ' -f1)
host=$(echo $line | cut -d' ' -f2)
slots=$(echo $line | cut -d' ' -f9-)
echo "$id ($host): $slots"
fi
done
Replication and Failover
Configure replication for high availability:
# Check replication status
redis-cli -c -p 7000 CLUSTER NODES | grep -E 'master|slave'
# Manually assign replica to master
redis-cli -p 7003 CLUSTER REPLICATE <master-node-id>
# Check replica role
redis-cli -p 7003 INFO replication
# Promote replica to master (if needed)
redis-cli -p 7003 CLUSTER FAILOVER
Handle node failures:
# Simulate node failure (stop a node)
sudo systemctl stop redis-cluster@7000
# Monitor cluster detection
redis-cli -c -p 7001 CLUSTER INFO
# Wait for cluster to fail over
sleep 20
# Check new master
redis-cli -c -p 7001 CLUSTER NODES | grep -E "7000|7003"
# Restart failed node
sudo systemctl start redis-cluster@7000
# Monitor recovery
redis-cli -c -p 7000 CLUSTER NODES
Configure failover thresholds:
# Connect to cluster node
redis-cli -c -p 7000
# Set node timeout (milliseconds)
CONFIG SET cluster-node-timeout 15000
# Persistence settings
CONFIG SET save "900 1"
CONFIG REWRITE
Dynamic Resharding
Add nodes to cluster without downtime:
# Start new empty nodes
for i in {7006..7007}; do
sudo mkdir -p /var/lib/redis-cluster/$i
sudo chown -R redis:redis /var/lib/redis-cluster/$i
# Create config
sudo sed "s/7000/$i/g" /etc/redis-cluster/redis-7000.conf > \
/etc/redis-cluster/redis-$i.conf
# Start service
sudo systemctl enable redis-cluster@$i
sudo systemctl start redis-cluster@$i
done
# Add new nodes to cluster
redis-cli --cluster add-node 192.168.1.10:7006 192.168.1.10:7000
redis-cli --cluster add-node 192.168.1.10:7007 192.168.1.10:7001 --cluster-slave
# Verify nodes joined
redis-cli -c -p 7000 CLUSTER NODES | grep 7006
# Reshard slots to new nodes
redis-cli --cluster reshard 192.168.1.10:7000 \
--cluster-from <source-node-id> \
--cluster-to <dest-node-id> \
--cluster-slots 1364 \
--cluster-yes
# Monitor resharding progress
redis-cli --cluster check 192.168.1.10:7000
Remove nodes from cluster:
# Reshard all slots away from node
redis-cli --cluster reshard 192.168.1.10:7000 \
--cluster-from <node-id-to-remove> \
--cluster-to <target-node> \
--cluster-slots 5461 \
--cluster-yes
# Once slots are gone, forget the node
redis-cli -p 7000 CLUSTER FORGET <node-id>
# On the forgotten node
redis-cli -p 7006 CLUSTER RESET
# Shut down the removed node
sudo systemctl stop redis-cluster@7006
Cluster Monitoring
Monitor cluster health and performance:
# Connect to cluster node
redis-cli -c -p 7000
-- Check cluster info
CLUSTER INFO
-- View all nodes
CLUSTER NODES
-- Get slot information
CLUSTER SLOTS
-- Check specific node
CLUSTER NODES | grep <node-id>
-- Get replicas of a node
CLUSTER REPLICAS <node-id>
-- View connection statistics
INFO clients
-- Check memory usage
INFO memory
-- Exit
EXIT
Create monitoring script:
#!/bin/bash
# /usr/local/bin/monitor-redis-cluster.sh
CLUSTER_PORT=7000
CLUSTER_HOST="192.168.1.10"
echo "=== Redis Cluster Health Check ==="
echo "Timestamp: $(date)"
# Check cluster state
echo ""
echo "Cluster Status:"
redis-cli -h $CLUSTER_HOST -p $CLUSTER_PORT CLUSTER INFO | \
grep -E "cluster_state|cluster_slots_assigned|cluster_known_nodes"
# Check node health
echo ""
echo "Node Status:"
redis-cli -h $CLUSTER_HOST -p $CLUSTER_PORT CLUSTER NODES | \
grep -E 'myself|master|slave' | awk '{print $1,$2,$7}' | head -10
# Check slot distribution
echo ""
echo "Slot Distribution:"
redis-cli -h $CLUSTER_HOST -p $CLUSTER_PORT CLUSTER SLOTS | \
grep -oE '^\d+' | sort -u | wc -l
echo "Total slots covered"
# Check for failed nodes
echo ""
echo "Failed Nodes:"
redis-cli -h $CLUSTER_HOST -p $CLUSTER_PORT CLUSTER NODES | \
grep -i fail || echo "None"
Client Connection
Connect to Redis Cluster from applications:
# Python example using redis-py
from redis.cluster import RedisCluster
# Create cluster connection
rc = RedisCluster(
startup_nodes=[
{"host": "192.168.1.10", "port": 7000},
{"host": "192.168.1.10", "port": 7001},
{"host": "192.168.1.10", "port": 7002}
],
decode_responses=True
)
# Set and get values
rc.set("mykey", "myvalue")
value = rc.get("mykey")
# Pipeline operations
pipe = rc.pipeline()
pipe.set("key1", "value1")
pipe.set("key2", "value2")
pipe.execute()
# Iterate over all keys (be careful with large datasets)
cursor = 0
all_keys = []
while True:
cursor, keys = rc.scan(cursor)
all_keys.extend(keys)
if cursor == 0:
break
Node.js example:
const redis = require('redis');
const cluster = redis.createCluster({
rootNodes: [
{ host: '192.168.1.10', port: 7000 },
{ host: '192.168.1.10', port: 7001 },
{ host: '192.168.1.10', port: 7002 }
],
socket: { connectTimeout: 5000 }
});
cluster.on('error', (err) => {
console.log('Cluster error:', err);
});
cluster.connect().then(() => {
return cluster.set('key', 'value');
});
Maintenance Operations
Perform maintenance safely:
# Rolling restart of cluster nodes
for node in 7000 7001 7002 7003 7004 7005; do
echo "Restarting node $node..."
sudo systemctl restart redis-cluster@$node
sleep 10
# Wait for node to rejoin
until redis-cli -p $node ping > /dev/null 2>&1; do
sleep 1
done
echo "Node $node rejoined"
done
# Backup cluster data
for i in {7000..7005}; do
redis-cli -p $i BGSAVE
done
# Flush specific database
redis-cli -c -p 7000 FLUSHDB
# Flush all databases
redis-cli -c -p 7000 FLUSHALL
Troubleshooting
Debug common cluster issues:
# Check cluster connectivity
redis-cli -h 192.168.1.10 -p 7000 CLUSTER MEET 192.168.1.10 7001
# Verify slot coverage
redis-cli --cluster check 192.168.1.10:7000
# Fix slot migration issues
redis-cli --cluster fix 192.168.1.10:7000
# Clear cluster state (only for recovery)
redis-cli -p 7000 CLUSTER RESET
# Check specific node
redis-cli -p 7000 CLUSTER NODES | grep <node-id>
# Monitor cluster events
redis-cli -p 7000 CLUSTER MYID
# Debug connection
redis-cli -h 192.168.1.10 -p 7000 DEBUG OBJECT mykey
Conclusion
Redis Cluster provides a scalable, highly available distributed system for storing large datasets without external dependencies. Its built-in sharding using hash slots, automatic failover, and dynamic resharding enable horizontal scaling while maintaining fault tolerance. By properly configuring replication, monitoring cluster health, and understanding maintenance procedures, you can operate production Redis Cluster deployments that support massive data volumes and high throughput requirements. Redis Cluster's simplicity combined with its powerful distributed capabilities makes it ideal for applications requiring both scaling and availability.


