Redis Cluster Configuración

Redis Cluster proporciona distributed data almacenamiento and automatic sharding across multiple nodos without requiring external clustering solutions. It enables horizontal scaling by partitioning data using consistent hashing (hash slots), proporciona automatic failover with réplica nodos, and maintains availability when failures occur. Esta guía completa cubre cluster creation, hash slot management, nodo operations, replication, resharding, failover mechanisms, and best practices for production Redis Cluster deployments.

Tabla de Contenidos

Architecture and Sharding

Redis Cluster distributes data across multiple nodos using 16,384 hash slots. Each key is mapped to a slot using CRC16 hashing, and each cluster nodo manages a range of slots. Clients connect to any nodo and are redirected to the correct nodo handling their key. This architecture enables linear scaling by adding nodos and automatic rebalancing of slots.

Cluster nodos communicate through a gossip protocol maintaining cluster topology information. Each nodo can have réplica nodos that copy its data, providing redundancy and enabling failover when a primary nodo becomes unavailable. The cluster remains operational as long as all hash slots are covered by at least one reachable nodo.

Instalación and Requisitos

Instala 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

# Verifica cluster support
redis-server --version
redis-cli --help | grep -i cluster

Crea cluster nodo directories:

# Crea user
sudo useradd -r -s /bin/false redis 2>/dev/null || true

# Crea data directories for 6 nodos (3 primary + 3 réplicas)
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

# Crea configuration directory
sudo mkdir -p /etc/redis-cluster

Cluster Initialization

Crea configuration files for each cluster nodo:

# Crea configuration for nodo 7000
sudo nano /etc/redis-cluster/redis-7000.conf

Add configuration:

# Cluster nodo configuration
puerto 7000
bind 0.0.0.0
cluster-enabled yes
cluster-config-file /var/lib/redis-cluster/7000/nodos.conf
cluster-nodo-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-réplicas-to-write 1
min-réplicas-max-lag 10

# Performance
tcp-backlog 511
timeout 0
tcp-keepalive 300

Crea configurations for remaining nodos:

# Crea nodos 7001-7005 with modified puerto 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

Crea systemd servicio template:

sudo nano /etc/systemd/system/[email protected]

Add:

[Unit]
Description=Redis Cluster Nodo %i
After=red.target

[Servicio]
Type=simple
User=redis
Group=redis

ExecStart=/usr/local/bin/redis-server /etc/redis-cluster/redis-%i.conf
ExecStop=/bin/kill -TERM $MAINPID

Reinicia=always
RestartSec=10

StandardOutput=journal
StandardError=journal

[Instala]
WantedBy=multi-user.target

Habilita and start all cluster nodos:

# Habilita servicios
for i in {7000..7005}; do
  sudo systemctl daemon-reload
  sudo systemctl enable redis-cluster@$i
done

# Inicia all nodos
for i in {7000..7005}; do
  sudo systemctl start redis-cluster@$i
done

# Verifica nodos are running
redis-cli -p 7000 ping
redis-cli -p 7005 ping

Crea the cluster using redis-cli:

# Crea cluster with 3 primary and 3 réplica nodos
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-réplicas 1 \
  --cluster-yes

# Verifica cluster creation
redis-cli -c -p 7000 CLUSTER INFO

# Get cluster nodos
redis-cli -c -p 7000 CLUSTER NODES

Hash Slot Gestión

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

# Analiza 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

Monitorea slot ownership:

#!/bin/bash
# Show slot distribution across nodos

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

Configura replication for high availability:

# Check replication status
redis-cli -c -p 7000 CLUSTER NODES | grep -E 'master|slave'

# Manually assign réplica to master
redis-cli -p 7003 CLUSTER REPLICATE <master-nodo-id>

# Check réplica role
redis-cli -p 7003 INFO replication

# Promote réplica to master (if needed)
redis-cli -p 7003 CLUSTER FAILOVER

Handle nodo failures:

# Simulate nodo failure (stop a nodo)
sudo systemctl stop redis-cluster@7000

# Monitorea 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"

# Reinicia failed nodo
sudo systemctl start redis-cluster@7000

# Monitorea recovery
redis-cli -c -p 7000 CLUSTER NODES

Configura failover thresholds:

# Conecta to cluster nodo
redis-cli -c -p 7000

# Set nodo timeout (milliseconds)
CONFIG SET cluster-nodo-timeout 15000

# Persistence settings
CONFIG SET save "900 1"
CONFIG REWRITE

Dynamic Resharding

Add nodos to cluster without downtime:

# Inicia new empty nodos
for i in {7006..7007}; do
  sudo mkdir -p /var/lib/redis-cluster/$i
  sudo chown -R redis:redis /var/lib/redis-cluster/$i
  
  # Crea config
  sudo sed "s/7000/$i/g" /etc/redis-cluster/redis-7000.conf > \
    /etc/redis-cluster/redis-$i.conf
  
  # Inicia servicio
  sudo systemctl enable redis-cluster@$i
  sudo systemctl start redis-cluster@$i
done

# Add new nodos to cluster
redis-cli --cluster add-nodo 192.168.1.10:7006 192.168.1.10:7000
redis-cli --cluster add-nodo 192.168.1.10:7007 192.168.1.10:7001 --cluster-slave

# Verifica nodos joined
redis-cli -c -p 7000 CLUSTER NODES | grep 7006

# Reshard slots to new nodos
redis-cli --cluster reshard 192.168.1.10:7000 \
  --cluster-from <source-nodo-id> \
  --cluster-to <dest-nodo-id> \
  --cluster-slots 1364 \
  --cluster-yes

# Monitorea resharding progress
redis-cli --cluster verifica 192.168.1.10:7000

Remueve nodos from cluster:

# Reshard all slots away from nodo
redis-cli --cluster reshard 192.168.1.10:7000 \
  --cluster-from <nodo-id-to-remove> \
  --cluster-to <target-nodo> \
  --cluster-slots 5461 \
  --cluster-yes

# Once slots are gone, forget the nodo
redis-cli -p 7000 CLUSTER FORGET <nodo-id>

# On the forgotten nodo
redis-cli -p 7006 CLUSTER RESET

# Shut down the removed nodo
sudo systemctl stop redis-cluster@7006

Cluster Monitoreo

Monitorea cluster health and performance:

# Conecta to cluster nodo
redis-cli -c -p 7000

-- Check cluster info
CLUSTER INFO

-- View all nodos
CLUSTER NODES

-- Get slot information
CLUSTER SLOTS

-- Check specific nodo
CLUSTER NODES | grep <nodo-id>

-- Get réplicas of a nodo
CLUSTER REPLICAS <nodo-id>

-- View connection statistics
INFO clients

-- Check memory usage
INFO memory

-- Exit
EXIT

Crea 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 nodo health
echo ""
echo "Nodo 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 nodos
echo ""
echo "Failed Nodos:"
redis-cli -h $CLUSTER_HOST -p $CLUSTER_PORT CLUSTER NODES | \
  grep -i fail || echo "None"

Client Connection

Conecta to Redis Cluster from applications:

# Python example using redis-py
from redis.cluster import RedisCluster

# Crea cluster connection
rc = RedisCluster(
    startup_nodes=[
        {"host": "192.168.1.10", "puerto": 7000},
        {"host": "192.168.1.10", "puerto": 7001},
        {"host": "192.168.1.10", "puerto": 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

Nodo.js example:

const redis = require('redis');

const cluster = redis.createCluster({
  rootNodes: [
    { host: '192.168.1.10', puerto: 7000 },
    { host: '192.168.1.10', puerto: 7001 },
    { host: '192.168.1.10', puerto: 7002 }
  ],
  socket: { connectTimeout: 5000 }
});

cluster.on('error', (err) => {
  console.log('Cluster error:', err);
});

cluster.connect().then(() => {
  return cluster.set('key', 'value');
});

Mantenimiento Operations

Perform maintenance safely:

# Rolling restart of cluster nodos
for nodo in 7000 7001 7002 7003 7004 7005; do
  echo "Restarting nodo $nodo..."
  sudo systemctl restart redis-cluster@$nodo
  sleep 10
  
  # Wait for nodo to rejoin
  until redis-cli -p $nodo ping > /dev/null 2>&1; do
    sleep 1
  done
  echo "Nodo $nodo rejoined"
done

# Respalda 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

Solución de Problemas

Depura common cluster issues:

# Check cluster connectivity
redis-cli -h 192.168.1.10 -p 7000 CLUSTER MEET 192.168.1.10 7001

# Verifica slot coverage
redis-cli --cluster verifica 192.168.1.10:7000

# Corrige 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 nodo
redis-cli -p 7000 CLUSTER NODES | grep <nodo-id>

# Monitorea cluster events
redis-cli -p 7000 CLUSTER MYID

# Depura connection
redis-cli -h 192.168.1.10 -p 7000 DEBUG OBJECT mykey

Conclusión

Redis Cluster proporciona 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 volúmenes and high throughput requirements. Redis Cluster's simplicity combined with its powerful distributed capabilities makes it ideal for applications requiring both scaling and availability.