Scale · 04 · Scalabilità
Sei nodi, 3 master e 3 replica, 16384 slot. Ogni comando di questa pagina è stato eseguito su un cluster reale.
Esercizio 4.1 — Creare il cluster
Sezione intitolata “Esercizio 4.1 — Creare il cluster”mkdir -p ~/redis-lab/cl && cd ~/redis-lab/clfor p in 7000 7001 7002 7003 7004 7005; do mkdir -p $p redis-server --port $p \ --cluster-enabled yes \ --cluster-config-file ~/redis-lab/cl/$p/nodes.conf \ --cluster-node-timeout 5000 \ --appendonly yes \ --dir ~/redis-lab/cl/$p \ --daemonize yes --logfile ~/redis-lab/cl/$p/r.logdonesleep 2
redis-cli --cluster create \ 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \ 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \ --cluster-replicas 1 --cluster-yesredis-cli -p 7000 CLUSTER INFO | grep -E 'cluster_state|cluster_slots_ok|cluster_known_nodes|cluster_size'Output atteso a regime:
cluster_state:okcluster_slots_ok:16384cluster_known_nodes:6cluster_size:3Topologia:
redis-cli -p 7000 CLUSTER NODES | awk '{split($2,a,"@"); print a[1], $3, $9}' | sortredis-cli -p 7000 CLUSTER SHARDS | head -20Esercizio 4.2 — MOVED: il client deve sapere
Sezione intitolata “Esercizio 4.2 — MOVED: il client deve sapere”redis-cli -p 7000 SET foo bar # senza -credis-cli -c -p 7000 SET foo bar # con -c (cluster mode)redis-cli -p 7000 CLUSTER KEYSLOT fooOutput misurato:
MOVED 12182 127.0.0.1:7002OK12182Verifica: un client non cluster-aware riceve MOVED e si ferma. redis-cli -c segue il redirect. In produzione questo è il requisito da imporre agli
AM: la libreria deve essere cluster-aware e mantenere la slot map in cache,
altrimenti ogni comando costa due round trip.
Esercizio 4.3 — Hash tag e CROSSSLOT
Sezione intitolata “Esercizio 4.3 — Hash tag e CROSSSLOT”redis-cli -p 7000 CLUSTER KEYSLOT "{user:1}:profile"redis-cli -p 7000 CLUSTER KEYSLOT "{user:1}:sessions"redis-cli -c -p 7000 MSET k1 1 k2 2redis-cli -c -p 7000 MSET "{u1}:a" 1 "{u1}:b" 2Output misurato:
1077810778CROSSSLOT Keys in request don't hash to the same slotOKVerifica: solo la parte tra graffe entra nella funzione di hash, quindi le
due chiavi {user:1}:* finiscono nello stesso slot e i comandi multi-chiave
funzionano. Senza hash tag, MSET/MGET/transazioni/Lua su più chiavi
falliscono con CROSSSLOT.
Conteggio chiavi per slot — da eseguire sul nodo proprietario:
SLOT=$(redis-cli -p 7000 CLUSTER KEYSLOT foo)redis-cli -p 7000 CLUSTER COUNTKEYSINSLOT $SLOT # 0: lo slot non è suoredis-cli -p 7002 CLUSTER COUNTKEYSINSLOT $SLOT # il valore realeredis-cli -p 7002 CLUSTER GETKEYSINSLOT $SLOT 10Esercizio 4.4 — Popolare e osservare la distribuzione
Sezione intitolata “Esercizio 4.4 — Popolare e osservare la distribuzione”for i in $(seq 1 200); do redis-cli -c -p 7000 SET key:$i $i > /dev/null; doneredis-cli --cluster call 127.0.0.1:7000 DBSIZEredis-cli --cluster info 127.0.0.1:7000Verifica: con 200 chiavi la distribuzione non è perfettamente uniforme — CRC16 è uniforme sugli slot, non sul numero di chiavi a campione piccolo. La distribuzione converge su volumi reali.
Esercizio 4.5 — Resharding online
Sezione intitolata “Esercizio 4.5 — Resharding online”Obiettivo: spostare 500 slot da un master a un altro senza downtime.
SRC=$(redis-cli -p 7000 CLUSTER MYID)DST=$(redis-cli -p 7001 CLUSTER MYID)
redis-cli --cluster reshard 127.0.0.1:7000 \ --cluster-from "$SRC" --cluster-to "$DST" \ --cluster-slots 500 --cluster-yesredis-cli -p 7000 CLUSTER NODES | awk '/master/{split($2,a,"@"); print a[1], $9, $10}'Output misurato:
127.0.0.1:7001 0-499 5461-10922127.0.0.1:7000 500-5460127.0.0.1:7002 10923-16383Verifica: durante la migrazione di uno slot il nodo sorgente risponde ASK
per le chiavi già spostate; il client cluster-aware segue il redirect
temporaneo. Il traffico non si ferma. Nota che 7001 ora possiede due range non
contigui: è normale e non ha impatto sulle prestazioni.
Bilanciamento automatico:
redis-cli --cluster rebalance 127.0.0.1:7000 # esegueredis-cli --cluster rebalance 127.0.0.1:7000 --cluster-simulate # dry-runEsercizio 4.6 — Failover manuale (manutenzione pianificata)
Sezione intitolata “Esercizio 4.6 — Failover manuale (manutenzione pianificata)”Da eseguire sulla replica che vuoi promuovere:
MASTER_ID=$(redis-cli -p 7000 CLUSTER MYID)REP=$(redis-cli -p 7000 CLUSTER NODES | awk -v m="$MASTER_ID" '$4==m{split($2,a,"@"); split(a[1],b,":"); print b[2]}')echo "replica di 7000 = $REP"redis-cli -p $REP CLUSTER FAILOVERsleep 5redis-cli -p 7000 CLUSTER NODES | awk '{split($2,a,"@"); print a[1], $3, $9}' | sortVerifica: CLUSTER FAILOVER senza opzioni è coordinato: il master
smette di accettare scritture, la replica si allinea all’offset, poi promuove.
Zero perdita di dati. CLUSTER FAILOVER FORCE salta il coordinamento (master
irraggiungibile), TAKEOVER salta anche il consenso degli altri master — usalo
solo in disaster recovery consapevole, può creare divergenza.
Questo è il comando da mettere nel runbook di patching: promuovi, patcha il nodo ex-master, riporta indietro.
Esercizio 4.7 — Failover automatico
Sezione intitolata “Esercizio 4.7 — Failover automatico”pgrep -a redis-server | grep 7001kill -9 <pid del master 7001>sleep 14redis-cli -p 7000 CLUSTER INFO | grep cluster_stateredis-cli -p 7000 CLUSTER NODES | awk '{split($2,a,"@"); print a[1], $3, $9}' | sortOutput misurato:
cluster_state:ok127.0.0.1:7001 master,fail127.0.0.1:7004 master 0-499 <- promossoVerifica: il cluster resta ok perché ogni slot ha un proprietario vivo. Il
nodo morto resta in fail finché non torna o non lo rimuovi con
CLUSTER FORGET. Tempo di failover ≈ cluster-node-timeout + elezione: con
5000 ms hai ~10 s di indisponibilità sugli slot di quel master.
Teardown:
for p in 7000 7001 7002 7003 7004 7005; do redis-cli -p $p SHUTDOWN NOSAVE 2>/dev/null; donerm -rf ~/redis-lab/clDomande di verifica
Sezione intitolata “Domande di verifica”- Perché
CLUSTER COUNTKEYSINSLOTrestituisce 0 su un nodo che non possiede lo slot, invece di un errore? - Differenza operativa tra
MOVEDeASK? - Un tenant è tutto sotto
{tenant:42}. Il resharding può alleggerirlo? - Master morto e
cluster-require-full-coverage yes: cosa succede agli slot degli altri master?
Prossimo passo: 05 · Osservabilità.