Redis: configurar persistência com AOF e RDB

Por padrão, o Redis é um banco de dados em memória, se o processo reiniciar sem persistência configurada, todos os dados se perdem. RDB cria snapshots periódicos enquanto AOF registra cada operação. A escolha entre os dois depende do equilíbrio entre performance e durabilidade que sua aplicação precisa.

RDB: snapshots periódicos

Configurar o mecanismo de snapshot RDB do Redis:

bash
# redis.conf — configuração de RDB:

# Ativar snapshots (salvar se N mudanças em X segundos):
save 3600 1      # salvar após 1 mudança em 1 hora
save 300 100     # salvar após 100 mudanças em 5 minutos
save 60 10000    # salvar após 10.000 mudanças em 1 minuto

# Desativar RDB completamente (se usando apenas AOF):
# save ""

# Arquivo de snapshot:
dbfilename dump.rdb
dir /var/lib/redis      # onde salvar o arquivo

# Compressão do RDB (economiza disco):
rdbcompression yes
rdbchecksum yes         # verificação de integridade no carregamento

# Comportamento em caso de falha no snapshot:
stop-writes-on-bgsave-error yes  # parar de aceitar writes se snapshot falhar
                                  # (garante que você saiba do problema)

# Verificar quando foi o último snapshot:
redis-cli LASTSAVE          # timestamp Unix do último RDB
redis-cli DEBUG SLEEP 0     # forçar snapshot manualmente: BGSAVE
redis-cli BGSAVE

AOF: Append Only File

Configurar o log de operações para durabilidade máxima:

bash
# redis.conf — configuração de AOF:

# Ativar AOF:
appendonly yes
appendfilename "appendonly.aof"

# Política de fsync (equilíbrio durabilidade/performance):
# always:   fsync após cada operação — mais seguro, mais lento (~5k ops/s)
# everysec: fsync a cada segundo — boa performance, perda máxima de 1s de dados (RECOMENDADO)
# no:       nunca faz fsync — SO decide quando escrever (risco de perda maior)
appendfsync everysec

# Reescrita automática do AOF (compactar o arquivo):
no-appendfsync-on-rewrite no   # não pausar fsync durante reescrita
auto-aof-rewrite-percentage 100  # reescrever quando AOF dobra de tamanho
auto-aof-rewrite-min-size 64mb  # tamanho mínimo para acionar reescrita

# Truncamento de AOF corrompido na inicialização:
aof-use-rdb-preamble yes  # usar RDB como base + AOF incremental (mais rápido para reload)

# Verificar integridade do AOF:
redis-check-aof --fix /var/lib/redis/appendonly.aof

# Forçar reescrita do AOF manualmente:
redis-cli BGREWRITEAOF

Configuração recomendada: RDB + AOF

Usar os dois mecanismos juntos para máxima proteção:

bash
# redis.conf — configuração de produção (RDB + AOF):

# RDB para snapshots rápidos (base para recovery):
save 3600 1
save 300 100
dbfilename dump.rdb
dir /var/lib/redis
rdbcompression yes

# AOF para durabilidade:
appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes   # formato híbrido: RDB base + AOF delta

# Memória máxima e política de evição:
maxmemory 1gb              # limitar uso de memória
maxmemory-policy allkeys-lru  # remover chaves menos usadas quando cheio
                              # noeviction: não remover (útil para dados persistentes)

# Para dados que NÃO devem ser evictados (ex: sessões críticas):
# maxmemory-policy noeviction

# Verificar uso atual:
redis-cli INFO memory | grep -E "used_memory_human|maxmemory_human|mem_fragmentation_ratio"
redis-cli INFO persistence | grep -E "rdb_|aof_"

# Saída esperada:
# used_memory_human: 256.00M
# maxmemory_human: 1024.00M
# aof_enabled: 1
# rdb_last_bgsave_status: ok
# aof_last_write_status: ok

Redis com Docker e persistência de volume

Garantir que os dados do Redis sobrevivem ao restart do container:

yaml
# docker-compose.yml — Redis com persistência:
services:
  redis:
    image: redis:7-alpine
    restart: always
    command: >
      redis-server
      --appendonly yes
      --appendfsync everysec
      --save 3600 1
      --save 300 100
      --maxmemory 512mb
      --maxmemory-policy allkeys-lru
      --requirepass ${REDIS_PASSWORD}
    ports:
      - "127.0.0.1:6379:6379"
    volumes:
      - redis_data:/data  # o diretório /data é onde o Redis salva os arquivos
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
      interval: 30s
      timeout: 5s
      retries: 3

volumes:
  redis_data:  # volume persistente — sobrevive ao docker compose down

# IMPORTANTE: sem o volume, reiniciar o container apaga todos os dados
# Mesmo com appendonly yes — os arquivos ficam no container, não no host

# Verificar que os arquivos estão no volume:
docker compose exec redis ls /data
# appendonly.aof  dump.rdb

Backup e restauração do Redis

Fazer backup dos dados e restaurar em caso de falha:

bash
#!/bin/bash
# Backup do Redis — copiar RDB e AOF para S3:

REDIS_DIR="/var/lib/redis"  # ou volume Docker: /var/lib/docker/volumes/redis_data/_data
TIMESTAMP=$(date +%Y%m%d_%H%M%S)

# Forçar snapshot antes do backup:
redis-cli -a "$REDIS_PASSWORD" BGSAVE
sleep 2  # aguardar conclusão

# Copiar arquivos para S3:
aws s3 cp "$REDIS_DIR/dump.rdb" "s3://meus-backups/redis/dump_$TIMESTAMP.rdb"
aws s3 cp "$REDIS_DIR/appendonly.aof" "s3://meus-backups/redis/aof_$TIMESTAMP.aof" 2>/dev/null || true

echo "Backup Redis concluído: $TIMESTAMP"

# Restaurar Redis de um backup:
# 1. Parar o Redis:
sudo systemctl stop redis
# 2. Copiar o arquivo de backup:
aws s3 cp "s3://meus-backups/redis/dump_TIMESTAMP.rdb" "$REDIS_DIR/dump.rdb"
aws s3 cp "s3://meus-backups/redis/aof_TIMESTAMP.aof" "$REDIS_DIR/appendonly.aof"
sudo chown redis:redis "$REDIS_DIR"/*.rdb "$REDIS_DIR"/*.aof
# 3. Iniciar o Redis:
sudo systemctl start redis
# 4. Verificar que os dados foram restaurados:
redis-cli -a "$REDIS_PASSWORD" DBSIZE  # número de chaves

Não quer configurar manualmente?

Implante o VPS em menos de 5 minutos com a Runstack. Infraestrutura da OPEN Datacenter, com servidores em São Paulo.

Perguntas frequentes

Para cache puro (dados que podem ser reconstruídos): desative tudo (save "" e appendonly no), máxima performance, zero overhead de I/O. Para cache com sessões de usuário (perda seria ruim): AOF com appendfsync everysec, perda máxima de 1 segundo. Para dados críticos que nunca podem se perder: AOF com appendfsync always, mais seguro, menor throughput (~5k writes/s vs ~100k sem persistência).

O BGSAVE usa fork() para salvar em background, não bloqueia o Redis principal. Mas fork() copia o espaço de memória (copy-on-write), o que pode causar latências de dezenas de milissegundos em sistemas com muita memória e muito I/O. Se isso é um problema: use AOF com aof-use-rdb-preamble yes (formato híbrido) ou aumente o intervalo do RDB (save 3600 1 apenas).

mem_fragmentation_ratio = used_memory_rss / used_memory. Valor ideal: 1.0 a 1.5. > 1.5: fragmentação alta, o Redis está reservando mais memória do SO do que realmente usa; considere reiniciar o Redis para desfragmentar. < 1.0: swap, o Redis está usando disco como memória (péssimo para performance). Redis 4.0+ tem desfragmentação ativa: configure activedefrag yes.

volatile-lru: evicta apenas chaves com TTL definido quando a memória enche, chaves sem TTL nunca são removidas. allkeys-lru: evicta qualquer chave (com ou sem TTL) pela política LRU. Para cache onde todas as chaves podem ser removidas: allkeys-lru. Para mistura de dados temporários (TTL) e permanentes (sem TTL): volatile-lru. Para dados que nunca devem ser removidos: noeviction (e configure alertas de memória).

Compare redis-cli DBSIZE antes e depois do restart. Se o número de chaves cair drasticamente: verifique redis-cli INFO persistence, rdb_last_bgsave_status e aof_last_write_status devem ser "ok". Se aof_enabled é 0 mas você queria AOF: o arquivo de configuração não foi aplicado. Verifique também o log do Redis (sudo journalctl -u redis ou docker logs redis) para mensagens de erro no carregamento do AOF/RDB.