Configure a production-ready Redis 7 cluster with multiple master nodes and replicas for high availability, automatic failover, and horizontal data distribution. Includes cluster initialization, topology configuration, and comprehensive health monitoring.
Prerequisites
- Multiple servers (minimum 3, recommended 6)
- Root or sudo access
- Basic Redis knowledge
- Network connectivity between nodes
What this solves
Redis clustering enables horizontal scaling and high availability by distributing data across multiple master nodes with automatic failover capabilities. This tutorial shows you how to configure a production-grade Redis 7 cluster with multiple masters and replica nodes for fault tolerance and performance scaling.
Step-by-step configuration
Install Redis 7
First, install Redis 7 on all cluster nodes. We'll configure six nodes total - three masters and three replicas.
sudo apt update
sudo apt install -y redis-server redis-tools
Create cluster directories
Create dedicated directories for each Redis cluster node with proper permissions.
sudo mkdir -p /etc/redis/cluster/{7000,7001,7002,7003,7004,7005}
sudo mkdir -p /var/lib/redis/cluster/{7000,7001,7002,7003,7004,7005}
sudo mkdir -p /var/log/redis/cluster
sudo chown -R redis:redis /var/lib/redis/cluster /var/log/redis/cluster
sudo chmod 750 /var/lib/redis/cluster/*
Configure Redis cluster nodes
Create configuration files for each cluster node. We'll start with the first master node on port 7000.
port 7000
bind 0.0.0.0
protected-mode yes
cluster-enabled yes
cluster-config-file nodes-7000.conf
cluster-node-timeout 15000
cluster-announce-ip 203.0.113.10
cluster-announce-port 7000
cluster-announce-bus-port 17000
appendonly yes
appendfilename "appendonly-7000.aof"
dir /var/lib/redis/cluster/7000
logfile /var/log/redis/cluster/redis-7000.log
loglevel notice
daemonize yes
pidfile /var/run/redis/redis-server-7000.pid
maxmemory 256mb
maxmemory-policy allkeys-lru
tcp-keepalive 300
timeout 0
tcp-backlog 511
databases 1
requirepass your-strong-password
masterauth your-strong-password
Create configurations for remaining nodes
Generate configuration files for the other five cluster nodes, adjusting ports and directories.
for port in 7001 7002 7003 7004 7005; do
sudo cp /etc/redis/cluster/7000/redis.conf /etc/redis/cluster/$port/redis.conf
sudo sed -i "s/7000/$port/g" /etc/redis/cluster/$port/redis.conf
sudo sed -i "s/17000/1$port/g" /etc/redis/cluster/$port/redis.conf
done
Update cluster announce IPs
Configure the cluster announce IP for each node. Replace with your actual server IPs in production.
sudo sed -i 's/203.0.113.10/203.0.113.11/g' /etc/redis/cluster/7001/redis.conf
sudo sed -i 's/203.0.113.10/203.0.113.12/g' /etc/redis/cluster/7002/redis.conf
sudo sed -i 's/203.0.113.10/203.0.113.13/g' /etc/redis/cluster/7003/redis.conf
sudo sed -i 's/203.0.113.10/203.0.113.14/g' /etc/redis/cluster/7004/redis.conf
sudo sed -i 's/203.0.113.10/203.0.113.15/g' /etc/redis/cluster/7005/redis.conf
Create systemd service files
Create systemd service files for each Redis cluster node to manage them independently.
[Unit]
Description=Redis Cluster Node 7000
After=network.target
[Service]
Type=forking
User=redis
Group=redis
ExecStart=/usr/bin/redis-server /etc/redis/cluster/7000/redis.conf
PIDFile=/var/run/redis/redis-server-7000.pid
TimeoutStopSec=0
Restart=always
[Install]
WantedBy=multi-user.target
Generate service files for all nodes
Create systemd service files for the remaining cluster nodes.
for port in 7001 7002 7003 7004 7005; do
sudo cp /etc/systemd/system/redis-cluster-7000.service /etc/systemd/system/redis-cluster-$port.service
sudo sed -i "s/7000/$port/g" /etc/systemd/system/redis-cluster-$port.service
done
Set proper ownership and permissions
Ensure Redis has proper ownership of all cluster directories and configuration files.
sudo chown -R redis:redis /etc/redis/cluster
sudo chmod 640 /etc/redis/cluster/*/redis.conf
sudo mkdir -p /var/run/redis
sudo chown redis:redis /var/run/redis
Configure firewall rules
Open the necessary ports for Redis cluster communication. Each node needs its data port and cluster bus port.
sudo ufw allow 7000:7005/tcp
sudo ufw allow 17000:17005/tcp
Start Redis cluster nodes
Enable and start all Redis cluster nodes using systemd.
sudo systemctl daemon-reload
for port in 7000 7001 7002 7003 7004 7005; do
sudo systemctl enable redis-cluster-$port
sudo systemctl start redis-cluster-$port
done
Verify nodes are running
Check that all Redis cluster nodes are running and listening on their assigned ports.
for port in 7000 7001 7002 7003 7004 7005; do
echo "Checking node $port:"
sudo systemctl status redis-cluster-$port --no-pager -l
ss -tlnp | grep :$port
done
Initialize the Redis cluster
Create the cluster by joining all nodes together. This assigns hash slots and creates the master-replica topology.
redis-cli -a your-strong-password --cluster create 203.0.113.10:7000 203.0.113.11:7001 203.0.113.12:7002 203.0.113.13:7003 203.0.113.14:7004 203.0.113.15:7005 --cluster-replicas 1
Configure cluster topology manually (alternative)
If you need specific master-replica assignments, you can configure the topology manually instead.
# First, create an empty cluster
redis-cli -a your-strong-password --cluster create 203.0.113.10:7000 203.0.113.11:7001 203.0.113.12:7002 --cluster-yes
Then add replicas to specific masters
redis-cli -a your-strong-password --cluster add-node 203.0.113.13:7003 203.0.113.10:7000 --cluster-slave
redis-cli -a your-strong-password --cluster add-node 203.0.113.14:7004 203.0.113.11:7001 --cluster-slave
redis-cli -a your-strong-password --cluster add-node 203.0.113.15:7005 203.0.113.12:7002 --cluster-slave
Configure cluster monitoring script
Create a monitoring script to check cluster health and node status.
#!/bin/bash
PASSWORD="your-strong-password"
NODES=("203.0.113.10:7000" "203.0.113.11:7001" "203.0.113.12:7002" "203.0.113.13:7003" "203.0.113.14:7004" "203.0.113.15:7005")
echo "Redis Cluster Health Check - $(date)"
echo "==========================================="
Check cluster info
redis-cli -h 203.0.113.10 -p 7000 -a $PASSWORD cluster info
echo -e "\nNode Status:"
for node in "${NODES[@]}"; do
IFS=':' read -r host port <<< "$node"
status=$(redis-cli -h $host -p $port -a $PASSWORD ping 2>/dev/null)
if [ "$status" = "PONG" ]; then
role=$(redis-cli -h $host -p $port -a $PASSWORD info replication | grep "role:" | cut -d: -f2 | tr -d '\r')
echo "$node: UP ($role)"
else
echo "$node: DOWN"
fi
done
echo -e "\nCluster Nodes:"
redis-cli -h 203.0.113.10 -p 7000 -a $PASSWORD cluster nodes
Make monitoring script executable
Set proper permissions on the health check script and create a systemd timer for regular monitoring.
sudo chmod 755 /usr/local/bin/redis-cluster-health.sh
sudo chown root:root /usr/local/bin/redis-cluster-health.sh
Test cluster failover
Test automatic failover by stopping a master node and verifying that its replica takes over.
# Check initial cluster state
redis-cli -h 203.0.113.10 -p 7000 -a your-strong-password cluster nodes
Stop a master node to test failover
sudo systemctl stop redis-cluster-7000
Wait a few seconds and check cluster state
sleep 10
redis-cli -h 203.0.113.11 -p 7001 -a your-strong-password cluster nodes
Restart the stopped node
sudo systemctl start redis-cluster-7000
Configure cluster backup script
Create an automated backup script for the Redis cluster data.
#!/bin/bash
BACKUP_DIR="/var/backups/redis-cluster"
DATE=$(date +%Y%m%d_%H%M%S)
PASSWORD="your-strong-password"
NODES=("7000" "7001" "7002" "7003" "7004" "7005")
mkdir -p $BACKUP_DIR/$DATE
for port in "${NODES[@]}"; do
echo "Backing up Redis node $port..."
# Create AOF backup
redis-cli -p $port -a $PASSWORD BGREWRITEAOF
# Wait for rewrite to complete
sleep 5
# Copy data files
cp /var/lib/redis/cluster/$port/appendonly-$port.aof $BACKUP_DIR/$DATE/
cp /var/lib/redis/cluster/$port/nodes-$port.conf $BACKUP_DIR/$DATE/
done
Compress backup
tar -czf $BACKUP_DIR/redis-cluster-$DATE.tar.gz -C $BACKUP_DIR $DATE
rm -rf $BACKUP_DIR/$DATE
Keep only last 7 days of backups
find $BACKUP_DIR -name "redis-cluster-*.tar.gz" -mtime +7 -delete
echo "Backup completed: $BACKUP_DIR/redis-cluster-$DATE.tar.gz"
Set up automated backups
Configure the backup script with proper permissions and create a systemd timer.
sudo chmod 755 /usr/local/bin/redis-cluster-backup.sh
sudo mkdir -p /var/backups/redis-cluster
sudo chown redis:redis /var/backups/redis-cluster
Test cluster data distribution
Verify that data is properly distributed across master nodes and replicated to slaves.
# Test data distribution
redis-cli -c -h 203.0.113.10 -p 7000 -a your-strong-password
Inside redis-cli:
SET user:1000 "John Doe"
SET user:2000 "Jane Smith"
SET user:3000 "Bob Wilson"
GET user:1000
GET user:2000
GET user:3000
Check which slots are assigned to each node
redis-cli -h 203.0.113.10 -p 7000 -a your-strong-password cluster slots
Verify your setup
# Check cluster status
/usr/local/bin/redis-cluster-health.sh
Verify all nodes are part of the cluster
redis-cli -h 203.0.113.10 -p 7000 -a your-strong-password cluster info
Check node roles and replication
redis-cli -h 203.0.113.10 -p 7000 -a your-strong-password cluster nodes
Test connectivity to each node
for port in 7000 7001 7002 7003 7004 7005; do
redis-cli -h 203.0.113.10 -p $port -a your-strong-password ping
done
Monitor cluster performance
Use Redis CLI tools to monitor cluster performance and health metrics.
# Monitor cluster statistics
redis-cli -h 203.0.113.10 -p 7000 -a your-strong-password --latency-history
Check memory usage across nodes
for port in 7000 7001 7002 7003 7004 7005; do
echo "Node $port memory usage:"
redis-cli -h 203.0.113.10 -p $port -a your-strong-password info memory | grep used_memory_human
done
Monitor cluster operations
redis-cli -h 203.0.113.10 -p 7000 -a your-strong-password --stat
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Cluster creation fails | Nodes not accessible or firewall blocking | Check firewall rules and node connectivity with telnet host port |
| MOVED errors during operations | Client not using cluster mode | Use redis-cli -c flag or configure client for cluster mode |
| Node shows as fail | Network partition or node crashed | Check node status with systemctl status redis-cluster-PORT |
| Replica not syncing | Authentication mismatch or network issues | Verify masterauth password matches requirepass in configs |
| Slot migration hanging | Large keys or network timeout | Increase cluster-node-timeout and check for large keys |
| Memory issues | No maxmemory policy set | Configure maxmemory-policy in redis.conf and restart nodes |
Next steps
- Set up Redis monitoring with Prometheus and Grafana dashboards
- Configure Redis Sentinel with SSL/TLS encryption and authentication for high availability
- Integrate Redis 7 with microservices architecture for caching and session management
- Implement Redis backup automation with RDB and AOF persistence
- Configure Redis cluster SSL encryption and authentication for production security
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Default configuration
CLUSTER_PASSWORD="${REDIS_PASSWORD:-your-strong-password-$(openssl rand -hex 8)}"
CLUSTER_IPS="${CLUSTER_IPS:-127.0.0.1,127.0.0.1,127.0.0.1,127.0.0.1,127.0.0.1,127.0.0.1}"
MEMORY_LIMIT="${MEMORY_LIMIT:-256mb}"
usage() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " -p PASSWORD Set Redis cluster password (default: auto-generated)"
echo " -i IPS Comma-separated list of 6 IPs for cluster nodes"
echo " -m MEMORY Memory limit per node (default: 256mb)"
echo " -h Show this help message"
echo ""
echo "Environment variables:"
echo " REDIS_PASSWORD - Redis cluster password"
echo " CLUSTER_IPS - Comma-separated cluster IPs"
echo " MEMORY_LIMIT - Memory limit per node"
exit 1
}
error() {
echo -e "${RED}ERROR: $1${NC}" >&2
exit 1
}
success() {
echo -e "${GREEN}$1${NC}"
}
warning() {
echo -e "${YELLOW}WARNING: $1${NC}"
}
cleanup() {
warning "Script failed. Cleaning up..."
systemctl stop redis-cluster-{7000..7005} 2>/dev/null || true
systemctl disable redis-cluster-{7000..7005} 2>/dev/null || true
rm -rf /etc/redis/cluster /var/lib/redis/cluster /var/log/redis/cluster
rm -f /etc/systemd/system/redis-cluster-*.service
systemctl daemon-reload
}
trap cleanup ERR
while getopts "p:i:m:h" opt; do
case $opt in
p) CLUSTER_PASSWORD="$OPTARG" ;;
i) CLUSTER_IPS="$OPTARG" ;;
m) MEMORY_LIMIT="$OPTARG" ;;
h) usage ;;
*) usage ;;
esac
done
# Check prerequisites
if [[ $EUID -ne 0 ]]; then
error "This script must be run as root"
fi
# Detect distribution
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_UPDATE="apt update"
PKG_INSTALL="apt install -y"
REDIS_PACKAGES="redis-server redis-tools"
FIREWALL_CMD="ufw"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
REDIS_PACKAGES="redis redis-tools"
FIREWALL_CMD="firewall-cmd"
;;
amzn)
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
REDIS_PACKAGES="redis redis-cli"
FIREWALL_CMD="firewall-cmd"
;;
*)
error "Unsupported distribution: $ID"
;;
esac
else
error "Cannot detect distribution"
fi
# Parse cluster IPs
IFS=',' read -ra CLUSTER_IP_ARRAY <<< "$CLUSTER_IPS"
if [ ${#CLUSTER_IP_ARRAY[@]} -ne 6 ]; then
error "Exactly 6 IP addresses required for cluster nodes"
fi
echo "[1/10] Installing Redis 7..."
$PKG_UPDATE
$PKG_INSTALL $REDIS_PACKAGES openssl
# Verify Redis installation
if ! redis-server --version | grep -q "Redis server"; then
error "Redis installation failed"
fi
echo "[2/10] Creating cluster directories..."
mkdir -p /etc/redis/cluster/{7000,7001,7002,7003,7004,7005}
mkdir -p /var/lib/redis/cluster/{7000,7001,7002,7003,7004,7005}
mkdir -p /var/log/redis/cluster
mkdir -p /var/run/redis
# Ensure redis user exists
if ! id redis >/dev/null 2>&1; then
useradd -r -s /bin/false redis
fi
chown -R redis:redis /var/lib/redis/cluster /var/log/redis/cluster /var/run/redis
chmod 750 /var/lib/redis/cluster/*
echo "[3/10] Creating Redis configuration files..."
for i in {0..5}; do
port=$((7000 + i))
cluster_ip="${CLUSTER_IP_ARRAY[$i]}"
cat > /etc/redis/cluster/$port/redis.conf << EOF
port $port
bind 0.0.0.0
protected-mode yes
cluster-enabled yes
cluster-config-file nodes-$port.conf
cluster-node-timeout 15000
cluster-announce-ip $cluster_ip
cluster-announce-port $port
cluster-announce-bus-port $((10000 + port))
appendonly yes
appendfilename "appendonly-$port.aof"
dir /var/lib/redis/cluster/$port
logfile /var/log/redis/cluster/redis-$port.log
loglevel notice
daemonize yes
pidfile /var/run/redis/redis-server-$port.pid
maxmemory $MEMORY_LIMIT
maxmemory-policy allkeys-lru
tcp-keepalive 300
timeout 0
tcp-backlog 511
databases 1
requirepass $CLUSTER_PASSWORD
masterauth $CLUSTER_PASSWORD
EOF
done
echo "[4/10] Setting configuration file permissions..."
chown -R redis:redis /etc/redis/cluster
chmod 640 /etc/redis/cluster/*/redis.conf
echo "[5/10] Creating systemd service files..."
for port in {7000..7005}; do
cat > /etc/systemd/system/redis-cluster-$port.service << EOF
[Unit]
Description=Redis Cluster Node $port
After=network.target
[Service]
Type=forking
User=redis
Group=redis
ExecStart=/usr/bin/redis-server /etc/redis/cluster/$port/redis.conf
PIDFile=/var/run/redis/redis-server-$port.pid
TimeoutStopSec=0
Restart=always
[Install]
WantedBy=multi-user.target
EOF
done
echo "[6/10] Reloading systemd and enabling services..."
systemctl daemon-reload
for port in {7000..7005}; do
systemctl enable redis-cluster-$port
done
echo "[7/10] Starting Redis cluster nodes..."
for port in {7000..7005}; do
systemctl start redis-cluster-$port
sleep 2
done
echo "[8/10] Configuring firewall..."
case "$FIREWALL_CMD" in
"ufw")
if systemctl is-active --quiet ufw; then
for port in {7000..7005}; do
ufw allow $port
ufw allow $((10000 + port))
done
fi
;;
"firewall-cmd")
if systemctl is-active --quiet firewalld; then
for port in {7000..7005}; do
firewall-cmd --permanent --add-port=$port/tcp
firewall-cmd --permanent --add-port=$((10000 + port))/tcp
done
firewall-cmd --reload
fi
;;
esac
echo "[9/10] Creating Redis cluster..."
sleep 5
cluster_endpoints=""
for i in {0..5}; do
port=$((7000 + i))
cluster_ip="${CLUSTER_IP_ARRAY[$i]}"
cluster_endpoints="$cluster_endpoints $cluster_ip:$port"
done
echo "yes" | redis-cli --cluster create $cluster_endpoints --cluster-replicas 1 -a "$CLUSTER_PASSWORD"
echo "[10/10] Verifying cluster status..."
sleep 3
cluster_status=$(redis-cli -h "${CLUSTER_IP_ARRAY[0]}" -p 7000 -a "$CLUSTER_PASSWORD" cluster info 2>/dev/null | grep cluster_state | cut -d: -f2 | tr -d '\r')
if [[ "$cluster_status" == "ok" ]]; then
success "Redis 7 cluster successfully installed and configured!"
echo ""
echo "Cluster Information:"
echo "==================="
echo "Nodes: ${CLUSTER_IPS}"
echo "Ports: 7000-7005"
echo "Password: $CLUSTER_PASSWORD"
echo ""
echo "Test connection:"
echo "redis-cli -h ${CLUSTER_IP_ARRAY[0]} -p 7000 -a '$CLUSTER_PASSWORD' -c"
echo ""
success "Installation completed successfully!"
else
error "Cluster creation failed. Status: $cluster_status"
fi
Review the script before running. Execute with: bash install.sh