Redis Cluster reparte las claves entre varios primarios y mantiene réplicas de cada uno, de modo que puedes crecer más allá de la memoria de un solo servidor y seguir funcionando si cae un nodo. Cada clave pertenece a uno de los 16.384 hash slots y cada primario sirve un rango de slots. En este tutorial crearás en Ubuntu 24.04 un clúster con tres primarios y tres réplicas, comprobarás cómo se redirigen las claves, probarás un failover y añadirás un nodo nuevo moviendo slots en caliente.
Requisitos previos
Para seguir esta guía necesitas:
- Seis servidores con Ubuntu 24.04 LTS, por ejemplo seis VPS de CubePath, en la misma red privada. Tres serán primarios y tres réplicas; 1 GB de RAM por nodo basta para las pruebas. En los ejemplos se usan las IP
10.0.0.11a10.0.0.16. - Un séptimo servidor (
10.0.0.17) para el paso de ampliación, opcional. - Un usuario no root con privilegios
sudoen cada servidor.
Tres primarios es el mínimo que admite Redis Cluster. Poner primario y réplica en servidores distintos es lo que permite sobrevivir a la caída de uno.
Si solo necesitas alta disponibilidad y tus datos caben en un servidor, Redis Sentinel es más sencillo: Redis Cluster obliga a que los clientes soporten el modo clúster y limita las operaciones con varias claves.
Paso 1: Instalar Redis en todos los nodos
Instala Redis 7.0 desde los repositorios de Ubuntu en los seis servidores:
sudo apt update
sudo apt install redis-server
Comprueba la versión:
redis-server --version
Redis server v=7.0.15 sha=00000000:0 malloc=jemalloc-5.3.0 bits=64 build=...
Paso 2: Activar el modo clúster
Genera una contraseña compartida para todo el clúster y guárdala en lugar seguro:
openssl rand -base64 32
En cada nodo, abre la configuración:
sudo nano /etc/redis/redis.conf
Modifica o añade estas directivas. En bind pon la IP privada de cada servidor y sustituye your_strong_password por la contraseña generada:
bind 127.0.0.1 -::1 10.0.0.11
requirepass your_strong_password
masterauth your_strong_password
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 5000
appendonly yes
cluster-enabled yesarranca Redis en modo clúster.cluster-config-filees un archivo que Redis gestiona solo (se guarda en/var/lib/redis) con el estado del clúster: nodos, slots y réplicas. No lo edites a mano.cluster-node-timeoutson los milisegundos sin respuesta tras los que un nodo se considera caído.masterauthpermite a las réplicas autenticarse contra su primario. Todos los nodos usan la misma contraseña.appendonly yesactiva la persistencia AOF para no perder las escrituras recientes si un nodo se reinicia.
Reinicia Redis y comprueba que está en modo clúster:
sudo systemctl restart redis-server
redis-cli -a 'your_strong_password' --no-auth-warning cluster info | head -1
cluster_state:fail
fail es lo esperado en este punto: el nodo está en modo clúster pero todavía no tiene slots asignados.
Paso 3: Abrir los puertos del clúster
Cada nodo usa dos puertos: 6379 para los clientes y 16379 (el puerto de datos más 10000) para el cluster bus, por donde los nodos intercambian estado y coordinan los failovers. Ábrelos solo a la red privada en los seis servidores:
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 16379 proto tcp
Si UFW no estaba activo, permite antes SSH con sudo ufw allow OpenSSH y actívalo con sudo ufw enable. Comprueba desde un nodo que llegas al bus de otro:
nc -zv 10.0.0.12 16379
Connection to 10.0.0.12 16379 port [tcp/*] succeeded!
Paso 4: Crear el clúster
Desde cualquiera de los nodos, crea el clúster con redis-cli --cluster create. La opción --cluster-replicas 1 indica una réplica por primario, así que con seis nodos obtendrás tres primarios y tres réplicas:
redis-cli -a 'your_strong_password' --no-auth-warning --cluster create \
10.0.0.11:6379 10.0.0.12:6379 10.0.0.13:6379 \
10.0.0.14:6379 10.0.0.15:6379 10.0.0.16:6379 \
--cluster-replicas 1
redis-cli propone un reparto de slots y pide confirmación:
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 10.0.0.15:6379 to 10.0.0.11:6379
Adding replica 10.0.0.16:6379 to 10.0.0.12:6379
Adding replica 10.0.0.14:6379 to 10.0.0.13:6379
...
Can I set the above configuration? (type 'yes' to accept):
Escribe yes. Al terminar verás:
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
Paso 5: Verificar el clúster
Comprueba el estado general:
redis-cli -a 'your_strong_password' --no-auth-warning cluster info | head -7
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
Lista los nodos con su papel y sus slots:
redis-cli -a 'your_strong_password' --no-auth-warning cluster nodes
3f1c...a2 10.0.0.11:6379@16379 myself,master - 0 0 1 connected 0-5460
8b7e...d4 10.0.0.12:6379@16379 master - 0 1727260000000 2 connected 5461-10922
c02a...91 10.0.0.13:6379@16379 master - 0 1727260000000 3 connected 10923-16383
e5d9...07 10.0.0.15:6379@16379 slave 3f1c...a2 0 1727260000000 1 connected
...
La primera columna es el ID de cada nodo; lo necesitarás para algunas operaciones. Para una revisión completa de consistencia usa:
redis-cli -a 'your_strong_password' --no-auth-warning --cluster check 10.0.0.11:6379
Paso 6: Trabajar con claves en el clúster
Un cliente normal que pide una clave a un nodo que no la tiene recibe un error MOVED. redis-cli sigue esas redirecciones con la opción -c:
redis-cli -c -h 10.0.0.11 -a 'your_strong_password' --no-auth-warning
Dentro de la consola:
10.0.0.11:6379> set usuario:1000 "Ana"
-> Redirected to slot [7319] located at 10.0.0.12:6379
OK
10.0.0.12:6379> set usuario:2000 "Luis"
-> Redirected to slot [1867] located at 10.0.0.11:6379
OK
10.0.0.11:6379> cluster keyslot usuario:2000
(integer) 1867
El slot se calcula con CRC16 sobre el nombre de la clave, así que una misma clave cae siempre en el mismo slot. Las operaciones con varias claves (MGET, MSET, transacciones, scripts Lua) solo funcionan si todas las claves están en el mismo slot. Para forzarlo usa hash tags: si una clave contiene {...}, solo se usa lo que hay entre llaves para calcular el slot.
10.0.0.11:6379> mset {usuario:1000}:nombre "Ana" {usuario:1000}:email "[email protected]"
-> Redirected to slot [7319] located at 10.0.0.12:6379
OK
10.0.0.12:6379> mget {usuario:1000}:nombre {usuario:1000}:email
1) "Ana"
2) "[email protected]"
Sin hash tags, ese MSET fallaría con CROSSSLOT Keys in request don't hash to the same slot. No abuses de ellos: si demasiadas claves comparten tag, acaban todas en un solo nodo.
Sal con exit.
Paso 7: Probar el failover
Detén Redis en un primario, por ejemplo 10.0.0.12:
sudo systemctl stop redis-server
Tras el cluster-node-timeout (5 segundos) y unos segundos de votación, su réplica pasa a primario. Compruébalo desde otro nodo:
redis-cli -a 'your_strong_password' --no-auth-warning cluster nodes | grep master
3f1c...a2 10.0.0.11:6379@16379 myself,master - 0 0 1 connected 0-5460
8b7e...d4 10.0.0.12:6379@16379 master,fail - 1727260100000 1727260095000 2 disconnected
c02a...91 10.0.0.13:6379@16379 master - 0 1727260110000 3 connected 10923-16383
a71b...5e 10.0.0.16:6379@16379 master - 0 1727260110000 7 connected 5461-10922
La clave usuario:1000 sigue disponible, ahora servida por 10.0.0.16. Arranca de nuevo el nodo caído:
sudo systemctl start redis-server
Vuelve como réplica del nuevo primario. Si quieres devolverle el papel de primario, conéctate a él y ejecuta un failover manual, que cambia los papeles sin pérdida de datos:
redis-cli -h 10.0.0.12 -a 'your_strong_password' --no-auth-warning cluster failover
OK
Advertenciasi caen a la vez un primario y su réplica, sus slots quedan sin servir y el clúster pasa a
cluster_state:failpara todas las claves. Por eso cada pareja debe estar en servidores físicos o zonas distintas. Si prefieres que el resto de slots siga respondiendo en ese caso, puedes ponercluster-require-full-coverage no.
Paso 8: Añadir un nodo y redistribuir slots
Para crecer, prepara un séptimo servidor (10.0.0.17) con los pasos 1 a 3. Después, desde cualquier nodo, únelo al clúster indicando el nuevo nodo y uno existente:
redis-cli -a 'your_strong_password' --no-auth-warning --cluster add-node 10.0.0.17:6379 10.0.0.11:6379
[OK] New node added correctly.
El nodo entra como primario vacío, sin slots. Reparte slots de los demás primarios hacia él. rebalance con --cluster-use-empty-masters calcula un reparto equilibrado y mueve las claves en caliente, sin cortar el servicio:
redis-cli -a 'your_strong_password' --no-auth-warning --cluster rebalance 10.0.0.11:6379 --cluster-use-empty-masters
>>> Rebalancing across 4 nodes. Total weight = 4.00
Moving 1366 slots from 10.0.0.11:6379 to 10.0.0.17:6379
...
Verifica con --cluster check: cada primario debe tener unos 4.096 slots. Para dar una réplica al nuevo primario, prepara otro servidor y añádelo con --cluster-slave:
redis-cli -a 'your_strong_password' --no-auth-warning --cluster add-node 10.0.0.18:6379 10.0.0.11:6379 \
--cluster-slave --cluster-master-id <id_de_10.0.0.17>
Para retirar un primario, primero vacía sus slots con redis-cli --cluster reshard hacia otros nodos y después elimínalo con redis-cli --cluster del-node 10.0.0.11:6379 <id_del_nodo>. Un nodo con slots no se puede eliminar.
Paso 9: Conectar una aplicación
Los clientes deben soportar el modo clúster: leen el mapa de slots, envían cada comando al nodo correcto y actualizan el mapa cuando reciben MOVED. Con Python, redis-py lo incluye:
sudo apt install python3-redis
nano cluster_test.py
from redis.cluster import RedisCluster, ClusterNode
rc = RedisCluster(
startup_nodes=[ClusterNode("10.0.0.11", 6379), ClusterNode("10.0.0.12", 6379)],
password="your_strong_password",
)
rc.set("pedido:42", "pendiente")
print(rc.get("pedido:42"))
print("Slot:", rc.keyslot("pedido:42"))
python3 cluster_test.py
b'pendiente'
Slot: 2873
Da varios nodos en startup_nodes para que el cliente pueda arrancar aunque uno esté caído.
Solución de problemas
--cluster create se queda en Waiting for the cluster to join. Los nodos no alcanzan el cluster bus de los demás. Comprueba que el puerto 16379 está abierto entre todos y que bind incluye la IP privada.
[ERR] Node 10.0.0.x:6379 is not empty. El nodo ya tiene claves o conoce otro clúster. En un nodo de pruebas, vacíalo con redis-cli -a 'your_strong_password' flushall y redis-cli -a 'your_strong_password' cluster reset, que borran sus datos.
--cluster check avisa de slots abiertos (open slots). Un resharding se interrumpió. redis-cli --cluster fix 10.0.0.11:6379 los cierra.
Una réplica no se sincroniza y el log muestra errores de autenticación. masterauth falta o no coincide con requirepass. Revisa sudo journalctl -u redis-server y /var/log/redis/redis-server.log en ese nodo.
Conclusión
Has creado un Redis Cluster de tres primarios con una réplica cada uno, has visto cómo se reparten las claves por slots, has probado un failover y has ampliado el clúster moviendo slots en caliente. Como siguientes pasos, mide la memoria de cada nodo con INFO memory y define maxmemory y una política de expulsión, programa copias de los archivos RDB/AOF de /var/lib/redis y revisa que tu aplicación usa hash tags en las operaciones con varias claves.
