In breve. Dipende da due impostazioni e da come Redis muore. Ho avviato due istanze con la stessa configurazione - le regole save del mio sviluppo, AOF spento - ho scritto mille chiavi in entrambe e le ho fermate in due modi. Quella uccisa con kill -9 è ripartita con zero chiavi; quella spenta in modo ordinato con mille. Con l'AOF acceso (appendonly yes, appendfsync everysec) anche il kill -9 ha restituito mille chiavi, e il prezzo l'ho misurato: il file occupa 1,7 volte lo spazio, l'avvio da 300.000 chiavi passa da 330 a 620 ms, e appendfsync always, su una connessione seriale, crolla da 32.718 a 876 scritture al secondo. Le uscite vengono da comandi eseguiti l'8 novembre 2026 su Redis 8.0.5 (nativo) e ripetuti su Redis 7.4.7 (immagine redis/redis-stack-server:latest). La configurazione di produzione non l'ho verificata: dove scrivo «questa istanza» parlo del mio sviluppo.
La domanda sbagliata e quella giusta
«Redis è persistente?» non ha risposta: Redis è un processo in memoria con due meccanismi di scrittura su disco opzionali. La domanda che produce una decisione si fa una chiave alla volta: se questa chiave sparisce adesso, che cosa si rompe?
Per la cache di un elenco di articoli la risposta è «niente, si ricostruisce». Per il marcatore che invalida i token emessi finora è «un utente che ho disconnesso torna connesso». Stessa istanza, stesso destino tecnico, costi incomparabili.
I due interruttori
Il primo è save, che non è un intervallo ma un elenco di condizioni «secondi, scritture». La riga del mio sviluppo, save 3600 1 300 100 60 10000, dice: salva dopo un'ora con una scrittura, cinque minuti con cento, o un minuto con diecimila.
Il secondo è appendonly: registra in coda a un file ogni comando che modifica i dati e li riesegue al riavvio. Il primo ti riporta a un momento del passato, il secondo a un istante prima della fine.
Il censimento viene prima della scelta
Prima di decidere ho contato, in sola lettura:
$ redis-cli -p 6379 dbsize
(integer) 2439
$ redis-cli -p 6379 --scan --count 1000 | sed -E 's/[0-9a-f]{6,}.*//; s/:.*//' | sort | uniq -c | sort -rn
2426 article
11 dataset
1 open_meteo_archive
1 kb_fiscal_paese_eval_green
Il 99% sono gli embedding degli articoli, ma è un'istanza senza traffico: il censimento che conta si fa sul codice, che dice quali famiglie esisteranno sotto carico. Nel backend ne ho trovate cinque.
jwt:revoked:{jti}etokensValidAfter:{userId}(JwtRevocationService, righe 42 e 45): perderle riapre token revocati fino alla scadenza dell'access token, 900 secondi (application.ymlriga 304).dq:idem:{scope}:{key}edq:lock:{key}(IdempotencyService, righe 57 e 60): perderle toglie la protezione dal doppio addebito dei crediti.bk-token:{token}(BookingTokenService, riga 66): perderli invalida i token, l'unica famiglia che sbaglia nel verso sicuro.{versione}:{nomeCache}::{chiave}, dal gestore di cache di Spring: si ricostruiscono alla prima richiesta, con un picco sul database.article:*: il servizio di ricerca li riscrive al proprio avvio, nella fase di lifespan (ml-service/app/main.py, riga 367). Costano un riavvio, non un dato.
Il criterio che tiene insieme le cinque righe non è «quanto è importante il dato» ma chi lo rimette al suo posto se sparisce, e la risposta cambia da riga a riga: il codice, un utente che rifà l'accesso, o nessuno. Letto così, l'elenco è una scala di gravità: in cima una perdita con conseguenze di sicurezza, in fondo una che si ripara riavviando un servizio. Una sola politica deve coprire entrambe, ed è qui che nasce il compromesso.
Quattro riavvii, quattro esiti
Gli esperimenti girano su una porta usa-e-getta, in cartelle temporanee, mai sull'istanza di sviluppo. Il copione: mille SET in pipe, un secondo e mezzo, morte, riavvio, DBSIZE.
Caso A: nessuna persistenza
$ D=$(mktemp -d)
$ redis-server --port 6399 --save "" --appendonly no --daemonize yes --dir $D
$ redis-cli -p 6399 info server | grep redis_version
redis_version:8.0.5
$ for i in $(seq 1 1000); do echo "SET k:$i v"; done | redis-cli -p 6399 --pipe
errors: 0, replies: 1000
$ redis-cli -p 6399 dbsize
(integer) 1000
$ sleep 1.6
$ kill -9 762280
$ ls -A $D # la cartella e' vuota: nessun file e' stato scritto
$ redis-server --port 6399 --save "" --appendonly no --daemonize yes --dir $D
$ redis-cli -p 6399 dbsize
(integer) 0
Le due opzioni che contano sono --save "", che cancella ogni condizione di salvataggio, e --appendonly no, che spegne il registro dei comandi. La prova non è lo 0 finale ma la riga di mezzo: ls -A sulla cartella dei dati non stampa niente, quindi non c'è nessun file da cui ripartire. Togli --save "" e sei nel Caso C, che sembra più prudente e finisce uguale.
Caso B: AOF a un secondo
$ D=$(mktemp -d)
$ redis-server --port 6399 --save "" --appendonly yes --appendfsync everysec --daemonize yes --dir $D
$ for i in $(seq 1 1000); do echo "SET k:$i v"; done | redis-cli -p 6399 --pipe
errors: 0, replies: 1000
$ sleep 1.6
$ kill -9 762378
$ ls -l $D/appendonlydir
-rw-rw-r-- 1 federicocalo federicocalo 88 Nov 8 07:57 appendonly.aof.1.base.rdb
-rw-r--r-- 1 federicocalo federicocalo 30916 Nov 8 07:57 appendonly.aof.1.incr.aof
-rw-r--r-- 1 federicocalo federicocalo 102 Nov 8 07:57 appendonly.aof.manifest
$ cat $D/appendonlydir/appendonly.aof.manifest
file appendonly.aof.1.base.rdb seq 1 type b
file appendonly.aof.1.incr.aof seq 1 type i startoffset 0
$ redis-server --port 6399 --save "" --appendonly yes --appendfsync everysec --daemonize yes --dir $D
$ redis-cli -p 6399 dbsize
(integer) 1000
Stesso kill -9, mille chiavi recuperate. E una scoperta: l'AOF non è un file. Dalla 7.0 è una cartella, appendonlydir, con un file di base in formato RDB, uno o più incrementali e un manifesto.
Caso C: la configurazione del mio sviluppo, e un kill -9
$ D=$(mktemp -d)
$ redis-server --port 6399 --save "3600 1 300 100 60 10000" --appendonly no --daemonize yes --dir $D
$ redis-cli -p 6399 config get save
save
3600 1 300 100 60 10000
$ for i in $(seq 1 1000); do echo "SET k:$i v"; done | redis-cli -p 6399 --pipe
errors: 0, replies: 1000
$ redis-cli -p 6399 info persistence | grep -E 'rdb_changes_since_last_save|rdb_last_save_time'
rdb_changes_since_last_save:1000
rdb_last_save_time:1794121073
$ sleep 1.6
$ kill -9 762500
$ ls -A $D # vuota: nessuna condizione di save e' stata raggiunta
$ redis-server --port 6399 --save "3600 1 300 100 60 10000" --appendonly no --daemonize yes --dir $D
$ redis-cli -p 6399 dbsize
(integer) 0
La configurazione prometteva persistenza e la cartella è rimasta vuota: mille scritture non bastano, la condizione più vicina è «un minuto e diecimila». La documentazione non usa mezzi termini: «Snapshotting is not very durable ... or you accidentally kill -9 your instance, the latest data written to Redis will be lost».
Caso D: la stessa configurazione, spenta per bene
$ D=$(mktemp -d)
$ redis-server --port 6399 --save "3600 1 300 100 60 10000" --appendonly no --daemonize yes --dir $D
$ for i in $(seq 1 1000); do echo "SET k:$i v"; done | redis-cli -p 6399 --pipe
errors: 0, replies: 1000
$ redis-cli -p 6399 shutdown # senza NOSAVE
$ ls -l $D
-rw-rw-r-- 1 federicocalo federicocalo 8987 Nov 8 07:57 dump.rdb
$ redis-server --port 6399 --save "3600 1 300 100 60 10000" --appendonly no --daemonize yes --dir $D
$ redis-cli -p 6399 dbsize
(integer) 1000
Esito opposto a parità di configurazione. La pagina di SHUTDOWN aggiunge il dettaglio che conta in produzione: con SIGTERM e SIGINT «the same shutdown sequence is performed». Un systemctl stop salva, un processo ucciso no. Il rovescio: senza AOF e senza direttiva save non si salva nemmeno allo spegnimento ordinato.
Gli stessi quattro casi su Redis 7.4.7
$ docker run -d --rm --name redis4-persistenza redis/redis-stack-server:latest
$ docker exec redis4-persistenza redis-cli info server | grep redis_version
redis_version:7.4.7
$ docker exec redis4-persistenza bash /tmp/in747.sh
>>> A dbsize dopo: 0 # save "", appendonly no, kill -9
>>> B dbsize dopo: 1000 # appendonly yes everysec, kill -9
>>> C dbsize dopo: 0 # save "3600 1 300 100 60 10000", kill -9
>>> D dbsize dopo: 1000 # stesse regole, SHUTDOWN ordinato
Lo script in747.sh è lo stesso copione di sopra, eseguito dentro il contenitore su una porta che non esce dall'host; le quattro righe che vedi sono i quattro DBSIZE dopo i quattro riavvii. La ripetizione non è pignoleria: il mio sviluppo è su 8.0.5 e la documentazione del progetto parla di Redis Stack 7, e nella stessa serie ho già trovato comportamenti che cambiano fra le due versioni. Qui non cambia nulla, e saperlo vale quanto il risultato.
Quanto si perde, e quanto costa non perdere nulla
Le tre politiche di appendfsync
Resta da decidere ogni quanto Redis chiede al sistema operativo di portare i byte sul disco: always a ogni gruppo di comandi, everysec ogni secondo, no quando decide il kernel. La frase che tutti citano va letta fino in fondo: «you may lose 1 second of data if there is a disaster».
Quel secondo non sono riuscito a perderlo
Ho provato a misurarlo e ho ottenuto un risultato che smentisce l'esperimento, non la documentazione. Decimila chiavi in pipe e kill -9 immediato, tre volte; poi tre volte dopo 1,2 secondi. Sei riavvii, zero perdite, su entrambe le versioni:
appendfsync=everysec, 10.000 SET in pipe, kill -9 SENZA attesa (3 giri)
giro 1: in memoria prima del kill = 10000 ; sopravvissute = 10000 ; perse = 0 ; aof incrementale = 318917 byte
giro 2: in memoria prima del kill = 10000 ; sopravvissute = 10000 ; perse = 0 ; aof incrementale = 318917 byte
giro 3: in memoria prima del kill = 10000 ; sopravvissute = 10000 ; perse = 0 ; aof incrementale = 318917 byte
lo stesso, ma con 1,2 s di attesa fra l'ultima scrittura e il kill -9 (3 giri)
giro 1: prima = 10000 ; sopravvissute = 10000 ; perse = 0
giro 2: prima = 10000 ; sopravvissute = 10000 ; perse = 0
giro 3: prima = 10000 ; sopravvissute = 10000 ; perse = 0
La spiegazione sta nel significato di fsync, e capirla ti evita di fidarti dell'esperimento sbagliato. Quando Redis esegue write() i byte lasciano il processo e finiscono nella cache del kernel: da quel momento sopravvivono alla sua morte. fsync serve contro la morte della macchina: corrente, kernel bloccato, disco scomparso. Un kill -9 non simula un disastro, simula un processo che muore, e sono due guasti diversi. La conseguenza pratica è scomoda: se il tuo guasto tipico è un processo che muore, cioè un rilascio sbagliato o il kernel che sceglie Redis per liberare memoria, everysec ti copre quanto always. La finestra di un secondo esiste, ma per vederla servirebbe staccare la corrente a una macchina: resta riferita dalla documentazione, non misurata da me.
Il prezzo di always, misurato in due modi
Prima misura: una sola connessione che invia un comando e aspetta la risposta, per tre secondi.
$ python3 -I writer.py 6399 log.txt # una connessione, SET seriali per 3 s
everysec 97814 scritture in 2.990 s -> 32718.1 scritture/s
always 2619 scritture in 2.991 s -> 875.6 scritture/s
no 96542 scritture in 2.992 s -> 32269.9 scritture/s
Un fattore 37. Seconda misura: lo stesso server con lo strumento ufficiale. -n 20000 è il numero di richieste, -t set limita la prova alla sola scrittura, e l'opzione che non ho scritto è quella decisiva: in mancanza di -c, redis-benchmark apre cinquanta client in parallelo. La colonna da leggere non è la prima ma p50, perché è quella che sente l'attesa del disco.
$ redis-benchmark -p 6399 -q -n 20000 -t set # Redis 8.0.5
--appendonly no -> SET: 84388.19 requests per second, p50=0.303 msec
--appendonly yes --appendfsync everysec -> SET: 85836.91 requests per second, p50=0.295 msec
--appendonly yes --appendfsync always -> SET: 22099.45 requests per second, p50=2.423 msec
$ docker exec redis4-persistenza redis-benchmark -p 7001 -q -n 20000 -t set # Redis 7.4.7
--appendonly no -> SET: 85470.09 requests per second, p50=0.295 msec
--appendonly yes --appendfsync everysec -> SET: 89285.71 requests per second, p50=0.287 msec
--appendonly yes --appendfsync always -> SET: 20986.36 requests per second, p50=2.455 msec
Con cinquanta client il fattore scende a circa 4 e la mediana sale da 0,3 a 2,4 ms. Le due misure non si contraddicono: con always «it means a single write and a single fsync» per un gruppo di comandi di più client, quello che la documentazione chiama group commit. Un numero preso con la concorrenza sbagliata fa decidere male.
Il file più grande e l'avvio più lento
Il terzo costo dell'AOF non è la scrittura ma il risveglio. Trecentomila chiavi identiche nei due casi, spegnimento ordinato, tre riavvii, misurando i millisecondi fino al primo PING riuscito:
dump.rdb = 10277887 byte
appendonlydir = 17378021 byte
RDB giro 1: 323 ms, 300000 chiavi
RDB giro 2: 374 ms, 300000 chiavi
RDB giro 3: 324 ms, 300000 chiavi
AOF giro 1: 678 ms, 300000 chiavi
AOF giro 2: 625 ms, 300000 chiavi
AOF giro 3: 557 ms, 300000 chiavi
L'AOF occupa 1,69 volte l'istantanea e si ricarica in poco meno del doppio. Le misure includono l'avvio del processo, con risoluzione di 5 ms: qui sono centinaia di millisecondi, su insiemi mille volte più grandi diventano minuti in cui il servizio non risponde.
I cinque campi di INFO persistence che rispondono
aof_enabled: 1 se l'AOF è attivo adesso. È il solo modo di sapere se le altre impostazioni contano.rdb_changes_since_last_save: quante modifiche non sono in un'istantanea. È il rischio corrente, in scritture.rdb_last_save_time: l'ultima istantanea, in secondi epoch. Convertila: può essere più vecchia di quanto immagini.rdb_last_bgsave_statuseaof_last_write_status:okoppure un errore. Un salvataggio che fallisce in silenzio è il peggio.aof_rewrite_in_progresseaof_last_bgrewrite_status: da controllare prima di riavviare, come prescrive la procedura di migrazione.
Le cinque righe rispondono a due domande diverse, e conviene separarle: le prime tre dicono quanto stai rischiando adesso, le altre due se puoi fidarti della risposta. Se devi guardarne una sola guarda rdb_changes_since_last_save, perché è la sola espressa nell'unità che ti interessa: le tue scritture, non un'impostazione.
Tre trappole che ho incontrato per davvero
Una appendfsync che non fa niente
$ redis-cli -p 6379 config get appendfsync
appendfsync
everysec
$ redis-cli -p 6379 info persistence | grep -E '^(aof_enabled|rdb_changes_since_last_save|rdb_last_save_time):'
aof_enabled:0
rdb_changes_since_last_save:0
rdb_last_save_time:1793815385
$ redis-cli -p 6379 info server | grep uptime_in_seconds
uptime_in_seconds:306204
È la mia istanza di sviluppo, in sola lettura. C'è scritto appendfsync everysec e non significa niente: aof_enabled vale 0, quindi quella riga regola la sincronizzazione di un file che nessuno scrive. In una revisione si legge «abbiamo l'AOF a un secondo»; è decorazione.
Le altre righe sono la misura vera: ultimo salvataggio 85 ore prima (il 2026-11-04 alle 19:03), zero modifiche non salvate. Un kill -9 adesso non perderebbe niente, ma non per merito della configurazione: perché da 85 ore nessuno scrive.
Accendere l'AOF a caldo e poi riavviare
$ redis-cli -p 6399 dbsize
(integer) 1000
$ redis-cli -p 6399 config set appendonly yes
OK
$ redis-cli -p 6399 info persistence | grep -E '^(aof_enabled|aof_rewrites|aof_base_size):'
aof_enabled:1
aof_rewrites:1
aof_base_size:8987
$ ls $D/appendonlydir
appendonly.aof.1.base.rdb
appendonly.aof.1.incr.aof
appendonly.aof.manifest
# primo riavvio: kill -9, e riparto CON appendonly yes
dbsize dopo il riavvio CON appendonly yes: 1000
# secondo riavvio: kill -9, e riparto CON appendonly no (configurazione a caldo non salvata)
dbsize dopo il riavvio CON appendonly no: 0
l'AOF e' ancora sul disco: appendonly.aof.1.base.rdb appendonly.aof.1.incr.aof appendonly.aof.manifest
Guarda l'ultima riga: i dati erano lì, completi, e Redis è ripartito vuoto perché nessuno gli aveva detto di leggerli. CONFIG SET cambia il server, non il file di configurazione: a chiudere il cerchio serve CONFIG REWRITE. La documentazione marca il passo come IMPORTANT: «If you forget this step, when you restart the server, the configuration changes will be lost and the server will start again with the old configuration, resulting in a loss of your data».
Accendere l'AOF a caldo ha prodotto subito una riscrittura (aof_rewrites:1) con un file di base di 8.987 byte: i dati già in memoria. Non parti da zero, parti da un'istantanea.
Una coda incompleta non impedisce l'avvio
$ stat -c%s $D/appendonlydir/appendonly.aof.1.incr.aof
15415
$ truncate -s -12 $D/appendonlydir/appendonly.aof.1.incr.aof
$ stat -c%s $D/appendonlydir/appendonly.aof.1.incr.aof
15403
$ redis-server --port 6399 --save "" --appendonly yes --appendfsync everysec --daemonize yes --dir $D
$ redis-cli -p 6399 dbsize
(integer) 499
$ redis-cli -p 6399 config get aof-load-truncated
aof-load-truncated
yes
Cinquecento chiavi scritte e sincronizzate, processo ucciso, dodici byte tolti a mano dalla fine del file incrementale per simulare una scrittura interrotta a metà comando: quattrocentonovantanove chiavi recuperate e il server è su. Identico su 7.4.7.
Il comportamento è voluto: con aof-load-truncated a yes, il valore per difetto, Redis tronca dove il file è coerente e prosegue «in order to guarantee availability after a restart». Puoi chiedergli di non partire, e allora serve redis-check-aof --fix. Preferisci un servizio su a cui manca l'ultimo comando, o un servizio giù?
Il controllo che dura trenta secondi
Su un'istanza che non conosci, questi quattro comandi bastano. Nessuno dipende dagli altri.
CONFIG GET appendonly: se rispondeno, ogni altra impostazioneappend*è decorazione.CONFIG GET save: vuoto significa nessuna istantanea automatica, nemmeno allo spegnimento.INFO persistence:rdb_changes_since_last_saveè quanto perderesti in questo istante.ls $(redis-cli config get dir | tail -1): quali file esistono davvero.
Non è una sequenza da eseguire in ordine: i primi due dicono che cosa Redis dovrebbe fare, il terzo quanto stai rischiando mentre li leggi, il quarto che cosa c'è davvero sul disco. Il quarto è quello che paga di più, perché è il solo che non si fida della configurazione: nella seconda trappola di qui sopra i file c'erano tutti, e guardarli bastava a non sbagliare diagnosi.
E se ti serve un punto fermo adesso
$ redis-cli -p 6399 dbsize
(integer) 1000
$ redis-cli -p 6399 bgsave
Background saving started
$ redis-cli -p 6399 info persistence | grep -E '^(rdb_changes_since_last_save|rdb_last_bgsave_status):'
rdb_changes_since_last_save:0
rdb_last_bgsave_status:ok
$ redis-cli -p 6399 set scritta_dopo_il_salvataggio 1
OK
$ redis-cli -p 6399 info persistence | grep '^rdb_changes_since_last_save:'
rdb_changes_since_last_save:1
$ kill -9
$ redis-server --port 6399 --save "" --appendonly no --daemonize yes --dir $D
$ redis-cli -p 6399 dbsize
(integer) 1000
$ redis-cli -p 6399 exists scritta_dopo_il_salvataggio
(integer) 0
BGSAVE produce un'istantanea su richiesta, in un processo figlio, e le due righe che raccontano la storia sono i due rdb_changes_since_last_save: 0 subito dopo il salvataggio, 1 dopo una sola scrittura. Quell'uno è l'intero preavviso che Redis ti dà. Infatti al riavvio tornano mille chiavi e exists risponde 0 sulla chiave scritta dopo. È il modello mentale giusto per l'RDB: non «i dati sono al sicuro», ma «fino a quell'istante».
Un commento che dà per scontata la persistenza
* <p>Redis is persistent (RDB/AOF) and a deploy only restarts the JVM — cached
* entries survive across deploys. If a deploy changes the logic that produces a
* cached value (without also changing its cache key), the old value keeps being
* served until its TTL naturally expires
È la riga 41 di infrastructure/cache/RedisCacheConfig.java. Sul problema di cui parla ha ragione: un rilascio riavvia la macchina virtuale Java senza toccare Redis, quindi la cache sopravvive, e il rimedio è il prefisso di versione. Ma la prima mezza frase, da sola, è una generalizzazione che il mio sviluppo smentisce: lì appendonly vale no. E la stessa istanza ospita le chiavi di revoca.
Una trappola gemella vive negli script. Due articoli di questo sito contengono righe come cp /var/lib/redis/appendonly.aof "$BACKUP_DIR/": corretto fino a Redis 6, sbagliato dalla 7.0. Uno script così copia niente ed esce bene.
Il trade-off, e cosa sceglierei
L'RDB costa poco, è compatto, si ricarica in metà tempo ed è perfetto da archiviare; in cambio perdi il periodo dall'ultima istantanea, di solito minuti. L'AOF con everysec non è più lento in scrittura, occupa 1,7 volte lo spazio, raddoppia l'avvio e riduce la finestra a un secondo. always la chiude e si paga da quattro a quaranta volte.
- Cache pura con TTL: nessuna persistenza, o solo RDB per non ripartire freddi. Un
fsyncper un valore che si ricalcola è spreco. - Chiavi la cui perdita è un rischio di sicurezza: AOF, perché il costo non è un picco di database ma un accesso che non dovrebbe esistere.
- Protezioni dal doppio addebito: AOF, sapendo che valgono quanto la finestra di perdita.
- Token monouso: indifferente, perché la perdita li invalida.
- Indici ricostruiti all'avvio di un servizio: nessuna persistenza, purché la ricostruzione sia nel codice e tu l'abbia letta.
È lo stesso criterio del censimento, applicato alla spesa: dove il dato lo ricostruisce il codice l'AOF è un costo senza contropartita, dove non lo ricostruisce nessuno il costo si paga e non si discute. Le due righe centrali sono le sole in cui la scelta ha conseguenze fuori dal tuo servizio.
Da qui la domanda che preferisco porre invece di prescrivere: se convivono dati sacrificabili e dati che non lo sono, hanno senso due istanze con due politiche? Ciascun dato pagherebbe solo il suo costo, al prezzo di un processo in più. Questo sito ne ha una sola. Il criterio si misura: quante scritture al secondo fanno le famiglie che non puoi perdere? Se sono poche, always dedicato costa quasi niente.
Cosa sai fare adesso
Sai che «Redis perde i dati al riavvio» non è una proprietà di Redis ma il risultato di tre cose: save, appendonly e come il processo viene fermato. Sai riconoscere una configurazione inerte, perché un CONFIG SET senza CONFIG REWRITE è una bomba a orologeria, e a quale guasto appartiene il secondo di everysec.
Il passo precedente, il confronto-e-cancella atomico, è in Lua, EVAL ed EVALSHA; la forma dei dati e quanto costano è nell'articolo sulle strutture dati di Redis. Cosa fa Redis quando lo spazio finisce è il prossimo articolo della serie: maxmemory, eviction e OOM. Per il piano di ripristino c'è disaster recovery e backup on-prem; per l'uso in un sistema di ricerca semantica, il setup di RAG e RediSearch.
Non sai dire cosa sopravviverebbe al prossimo riavvio della tua Redis? Prenota una call →
Domande frequenti
Se riavvio Redis perdo i dati?
Dipende da come lo riavvii e da come è configurato. Con le regole save del mio sviluppo e l'AOF spento, un kill -9 mi ha lasciato zero chiavi su mille e uno spegnimento ordinato tutte: con SIGTERM Redis esegue la stessa sequenza di spegnimento, quindi un systemctl stop salva e un processo ucciso no.
Meglio RDB o AOF?
RDB se i dati si ricostruiscono e vuoi un file compatto con avvio rapido: su 300.000 chiavi occupava 9,8 MB e ripartiva in circa 330 ms, contro 16,6 MB e 620 ms dell'AOF. AOF se perdere una chiave costa più di un ricalcolo. Usandoli entrambi, al riavvio Redis ricostruisce dall'AOF.
Quanto costa appendfsync always?
Dipende dalla concorrenza, e per questo le risposte in rete si contraddicono. Su una connessione seriale ho misurato 876 scritture al secondo contro 32.718 di everysec, un fattore 37; con cinquanta client paralleli 22.099 contro 85.837 richieste al secondo, un fattore 4. La documentazione lo spiega: più scritture concorrenti entrano nello stesso fsync.
Fonti
- Redis, Redis persistence - le tre politiche di
appendfsync, le frasi citate sopra sul secondo perduto e sukill -9, l'AOF multi-parte dalla 7.0,aof-load-truncated, il passaggio a caldo e il group commit, consultata il 2026-11-08. - Redis, comando SHUTDOWN - l'equivalenza fra
SHUTDOWNe i segnaliSIGTERM/SIGINT, e l'istanza senza AOF e senzasaveche non salva allo spegnimento, consultata il 2026-11-08. - Redis, comando CONFIG REWRITE - che cosa riscrive e perché serve dopo un
CONFIG SET, consultata il 2026-11-08. - Redis, comando BGSAVE - l'istantanea su richiesta prodotta da un processo figlio, consultata il 2026-11-08.
- Misure mie, l'8 novembre 2026, coi comandi dei blocchi sopra: Redis 8.0.5 nativo e 7.4.7 (
redis/redis-stack-server:latest), istanze usa-e-getta sulla porta 6399, sola lettura sulla 6379. - Codice di questo sito, l'8 novembre 2026:
JwtRevocationService.java(42, 45),IdempotencyService.java(57, 60),BookingTokenService.java(66),RedisCacheConfig.java(41),application.yml(304),ml-service/app/main.py(367).
Se ne apri una sola, apri la prima: contiene cinque delle sei frasi che ho citato, compresa quella sul kill -9 e la procedura di passaggio all'AOF che la seconda trappola viola. Le altre tre pagine servono a controllare un dettaglio, non a capire il meccanismo; le ultime due voci non sono documentazione ma il modo di rifare le misure.
Commenti
Caricamento commenti...
Accedi per commentare