Saudações.
Esse tutorial é um guia rápido de instalação e uso do Valkey, serviço de chave-valor e pub/sub semelhante ao Redis (fork antigo) e que hoje supera em muito o Redis.
Pré-requisitos (constam em outros artigos aqui do blog):
- Instalação do Linux (Debian ou Alpine);
- Internet no servidor (sua VPS ou host);
- Docker CE instalado (opcional);
1 – Sobre Valkey
O Valkey é um software de banco de dados firmado no conceito de chave-valor armazenado em RAM, seguindo a filosofia “RAM is the new disk” (a memória é o novo disco).
Seus fundamentos são:
- Chave/valor: Armazenar e recuperar o valor de chaves (nome=Patrick);
- Cache: As chaves podem ter TTL (tempo de vida) e expirar se não forem renovadas;
- Pub/sub: Um canal que funciona como sala de chat em tempo real para programas;
- RAM como armazenamento principal;
- Disco como backup das caches:
- Backup em tempo real nos arquivos AOF (log de criação e alteração das chaves);
- Backup completo em arquivos RDB (snapshots completos da memória);
Para que ele atinja velocidades extremas, o ambiente deve:
- Possui baixa latência de rede;
- Possuir uma CPU com muita memória CACHE (L1, L2, L3);
- Recomendável: Mínimo 16 MB de CACHE total;
- Ótimo: Mínimo 128 MB de CACHE (caro!);
- Possuir memória de alta-velocidade (DDR4 ou superior);
- Reservar núcleos exclusivos para que ele não perca o CACHE para outros programas;
As operações de backup AOF/RDB rodam em paralelo sem penalizar as operações, o uso de unidades NVME ou SSD ajudam a garantir a persistência contra desastres.
2 – Ajustes no sistema
Alguns ajustes são recomendados no sistema para atender melhor às demandas de alta-performance no Valkey.
Se você rodar ele com outros sistemas em um ambiente muito híbrido não será necessário mexer (você está em apuros mesmo).
2.1 – Ajustes básicos
Você deve, previamente:
- Data/hora do servidor finamente sincronizada com NTP/NTS
- Manter a coerência entre o IP do servidor e o nome de DNS (real ou fictício) no arquivo /etc/hosts
- Possuir um DNS funcionando bem e rápido, configure o IP em /etc/resolv.conf
2.2 – Ajustes no sysfs
É necessário ativar o “tranparent hugepages” pois ele tentará fazer manutenção da memória RAM e isso pode interromper o Valkey por alguns microssegundos.
# - Criar manifesto de preenchimento de configs durenate o boot:
(
echo 'w /sys/kernel/mm/transparent_hugepage/enabled - - - - never';
) > /etc/tmpfiles.d/transp-hugepage-disable.conf;
# Desativar hugepages transparente imediatamente
echo never > /sys/kernel/mm/transparent_hugepage/enabled;
2.3 – Ajustes no sysctl
Esses ajustes mudam o comportamento padrão do Kernel Linux.
# Gestao de overcommit de memoria
echo "vm.overcommit_memory=1" > /etc/sysctl.d/076-ram-overcommit.conf;
# Aumentar capacidades de rede do protocolo TCP
(
echo "net.core.rmem_default=31457280";
echo "net.core.wmem_default=31457280";
echo "net.core.rmem_max=134217728";
echo "net.core.wmem_max=134217728";
echo "net.core.netdev_max_backlog=250000";
echo "net.core.optmem_max=33554432";
echo "net.core.default_qdisc=fq";
echo "net.core.somaxconn=65535";
) > /etc/sysctl.d/051-net-core.conf;
# Aumentar buffers e acelerar o inicio das conexoes
(
echo "net.ipv4.tcp_sack = 1";
echo "net.ipv4.tcp_timestamps = 1";
echo "net.ipv4.tcp_low_latency = 1";
echo "net.ipv4.tcp_max_syn_backlog = 65535";
echo "net.ipv4.tcp_rmem = 4096 87380 67108864";
echo "net.ipv4.tcp_wmem = 4096 65536 67108864";
echo "net.ipv4.tcp_mem = 6672016 6682016 7185248";
echo "net.ipv4.tcp_congestion_control=htcp";
echo "net.ipv4.tcp_mtu_probing=1";
echo "net.ipv4.tcp_moderate_rcvbuf =1";
echo "net.ipv4.tcp_no_metrics_save = 1";
) > /etc/sysctl.d/052-net-tcp-ipv4.conf;
Aplicar alterações de sysctl:
# Comando (sysctl -p) requer tudo em um unico arquivo:
(
echo "# NAO EDITAR";
echo "# Gerado automaticamente via:";
echo "# cat /etc/sysctl.d/*.conf > /etc/sysctl.conf";
echo;
cat /etc/sysctl.d/*.conf;
echo;
) > /etc/sysctl.conf;
# Aplicar imediatamente:
sysctl -q --system 2>/dev/null;
sysctl -q -p 2>/dev/null;
3 – Valkey no Debian (host)
Esse capítulo aborda o uso do Valkey direto no HOST em um servidor Debian (VPS, VM).
# Atualizar sistema local
apt -y update;
apt -y upgrade;
apt -y dist-upgrade;
apt -y autoremove;
# Instalar o Valkey
apt -y install valkey-tools;
apt -y install valkey-server;
apt -y install valkey-sentinel;
# Ativar serviço servidor durante o boot
systemctl enable valkey-server;
systemctl enable valkey-sentinel;
4 – Valkey no Alpine (host)
Esse capítulo aborda o uso do Valkey direto no HOST em um servidor Alpine (VPS, VM).
# Atualizar sistema local
apk update;
apk upgrade;
# Instalar o Valkey
apk add valkey;
apk add valkey-cli;
apk add valkey-tls;
apk add valkey-benchmark;
# Ativar serviço servidor durante o boot
rc-update add valkey default;
rc-update add valkey-sentinel default;
5 – Configurações básicas
Cada caso pede uma forma diferente de usar o Valkey, vou apresentar algumas configurações de exemplo.
As configurações podem ser passados para o valkey-server via argumentos ou pelo arquivo de configuração.
Nos argumentos vc deve preceder a palavra de “–” seguida de espaço e o valor. Exemplo:
5.1 – Cache puro em RAM
Exemplo rodando em linha de comando:
# Rodar valkey-server com argumentos na linha de comando:
# - Abrir apenas no IP de loopback ipv4 (127.0.0.1) e ipv6 (::1)
# - Porta 7000
# - Limite de RAM: 128 MB
# - Sem salvar nada em disco
/usr/bin/valkey-server \
\
--bind 127.0.0.1 ::1 \
--port 7000 \
--databases 256 \
--maxmemory 128mb \
--appendonly no \
--dir /run \
--save "" \
--loglevel notice;
No arquivo de configuração basta informar uma palavra por linha seguida de espaço e o valor. Exemplo:
bind 127.0.0.1 ::1
port 7000
databases 256
maxmemory 128mb
appendonly no
dir /run
save ""
loglevel notice
Rodando baseado no arquivo acima (/etc/valkey/valkey-server-cache.conf):
# Rodar usando configuracao especifica:
# - Modo debug:
/usr/bin/valkey-server /etc/valkey/valkey-server-cache.conf --loglevel verbose;
# - Modo normal:
/usr/bin/valkey-server /etc/valkey/valkey-server-cache.conf;
5.2 – Persistência Básica
Nessa configuração o Valkey irá armazenar as chaves alteradas periodicamente de maneira relaxada, sem urgência.
Pode perder dados em casos de panes por falta de memória (OOM), assassinato do serviço ou desligamento acidental do servidor.
# Porta de escuta
bind 127.0.0.1 ::1
port 7001
# Opcoes
pidfile /run/valkey/valkey-7001.pid
logfile /var/log/valkey/valkey-7001.log
loglevel notice
protected-mode no
tcp-backlog 4096
timeout 0
tcp-keepalive 30
# Persistência relaxada
# RDB Snapshots:
dir /var/lib/valkey
dbfilename valkey-7001.rdb
save 900 1
save 300 100
save 60 10000
rdbcompression no
rdbchecksum yes
# AOF timeline
appendonly yes
appendfilename valkey-7001.aof
appenddirname aof7001
appendfsync everysec
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
# Gestao de Memoria
maxmemory 256mb
maxmemory-policy allkeys-lru
maxmemory-samples 5
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
# Performance em Ambientes Saturados
hz 10
dynamic-hz yes
io-threads 2
Rodando baseado no arquivo acima (/etc/valkey/valkey-server-db-relax.conf):
# Rodar usando configuracao especifica:
# - Modo debug:
/usr/bin/valkey-server /etc/valkey/valkey-server-db-relax.conf --loglevel verbose;
# - Modo normal:
/usr/bin/valkey-server /etc/valkey/valkey-server-db-relax.conf;
5.3 – Persistência em tempo real
Essa configuração é focada em casos onde você deseja que o Valkey seja seu banco de dados persistente sem abrir margem para a perda de nenhuma chave, ou seja, o banco de dados na memória será salvo em disco a cada byte alterado usando apenas AOF (o RDB cria pontos no tempo que podem ficar atrasados em relação ao AOF).
# Porta de escuta
bind 127.0.0.1 ::1
port 7002
# Opcoes
pidfile /run/valkey/valkey-7002.pid
logfile /var/log/valkey/valkey-7002.log
loglevel notice
protected-mode no
tcp-backlog 4096
timeout 0
tcp-keepalive 30
# Persistência relaxada
# RDB Snapshots:
dir /var/lib/valkey
dbfilename valkey-7002.rdb
save ""
rdbcompression no
rdbchecksum yes
# AOF timeline
appendonly yes
appendfilename valkey-7002.aof
appenddirname aof7002
appendfsync always
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble no
# Gestao de Memoria
maxmemory 256mb
maxmemory-policy allkeys-lru
maxmemory-samples 5
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
# Performance em Ambientes Saturados
hz 10
dynamic-hz yes
io-threads 2
Rodando baseado no arquivo acima (/etc/valkey/valkey-server-database.conf):
# Rodar usando configuracao especifica:
/usr/bin/valkey-server /etc/valkey/valkey-server-database.conf;
6 – Rodando Valkey no Docker
O Valkey tem imagens para Docker finamente compiladas para alta performance.
Vou começar pela execução mais simples para estudos usando “docker run”.
6.1 – Rede Docker
Padrão “network_public” que costumo usar nos meus tutoriais:
# Rede de containers FreeRadius
docker network create network_public \
-d bridge \
-o com.docker.network.bridge.name=br-net-public \
-o com.docker.network.driver.mtu=1500 \
-o com.docker.network.bridge.gateway_mode_ipv4=nat-unprotected \
--subnet 10.249.0.0/16 \
--gateway 10.249.255.254;
6.2 – Container para Cache puro em RAM
Container sem uso de disco, apenas memória. Observe que reservei no container a mesma quantidade de memória que informei ao valkey-server (192 MB):
# Rodar valkey-server em container
# - Limite de RAM: 128 MB
# - Reserva de RAM: 192 MB
# - Sem salvar nada em disco
# Baixar imagem
docker pull valkey/valkey:9.0.3;
# Renovar/rodar
docker rm -f valkey-cache 2>/dev/null;
docker run \
-d --restart=always \
--name valkey-cache \
-h valkey-cache.intranet.br \
\
--tmpfs /run:rw,noexec,nosuid,size=16m \
--read-only \
\
--cpus=1 \
--memory=256m \
--memory-swap=256m \
--memory-reservation=192m \
--oom-score-adj=-500 \
\
--ulimit nofile=1048576:1048576 \
--ulimit memlock=-1 \
--sysctl net.core.somaxconn=16384 \
\
--network network_public \
\
--health-cmd="valkey-cli -p 6379 ping | grep -q PONG" \
--health-interval=5s \
--health-timeout=3s \
--health-start-period=10s \
--health-retries=3 \
\
valkey/valkey:9.0.3 \
valkey-server \
--bind '0.0.0.0 ::' \
--port 6379 \
--protected-mode no \
--set-proc-title no \
--tcp-backlog 16384 \
--tcp-keepalive 30 \
--timeout 0 \
\
--databases 256 \
\
--maxmemory 192mb \
\
--appendonly no \
--dir /run \
--save "" \
\
--loglevel notice;
Analisando e rodando testes no container:
# Analisando
docker inspect valkey-cache;
docker diff valkey-cache;
docker logs valkey-cache;
docker logs -f valkey-cache;
# Testar se o container está funcionando:
docker exec -it valkey-cache valkey-cli -p 6379 ping;
# Obter terminal valkey-cli:
docker exec -it valkey-cache valkey-cli;
6.2 – Container com Persistência Básica
Container com persistência básica em disco (volume):
# Rodar valkey-server em container
# - Limite de RAM: 384 MB
# - Reserva de RAM: 256 MB
# - Sem salvar nada em disco
# Pasta para salvar dados no volume
mkdir -p /storage/valkey-db-relax;
# Ajuste de permissao na pasta do volume
chown -R 999:999 /storage/valkey-db-relax;
# Renovar/rodar
docker rm -f valkey-db-relax 2>/dev/null;
docker run \
-d --restart=always \
--name valkey-db-relax \
-h valkey-db-relax.intranet.br \
\
--read-only \
--tmpfs /run:rw,noexec,nosuid,size=16m \
\
--cpus=1 \
--memory=384m \
--memory-swap=384m \
--memory-reservation=256m \
--oom-score-adj=-500 \
\
--ulimit nofile=1048576:1048576 \
--ulimit memlock=-1 \
--sysctl net.core.somaxconn=16384 \
\
--network network_public \
\
-v /storage/valkey-db-relax:/data \
-w /data \
\
--health-cmd="valkey-cli -p 6379 ping | grep -q PONG" \
--health-interval=5s \
--health-timeout=3s \
--health-start-period=10s \
--health-retries=3 \
\
valkey/valkey:9.0.3 \
valkey-server \
--bind '0.0.0.0 ::' \
--port 6379 \
--loglevel notice \
--protected-mode no \
--tcp-backlog 4096 \
--timeout 0 \
--tcp-keepalive 30 \
--dir /data \
--dbfilename valkey-db-relax.rdb \
--save 900 1 \
--save 300 100 \
--save 60 10000 \
--rdbcompression no \
--rdbchecksum yes \
\
--appendonly yes \
--appendfilename valkey-db-relax.aof \
--appenddirname aof-db-relax \
--appendfsync everysec \
\
--no-appendfsync-on-rewrite yes \
--auto-aof-rewrite-percentage 100 \
--auto-aof-rewrite-min-size 64mb \
--aof-load-truncated yes \
--aof-use-rdb-preamble yes \
\
--maxmemory 256mb \
--maxmemory-policy allkeys-lru \
--maxmemory-samples 5 \
--lazyfree-lazy-eviction yes \
--lazyfree-lazy-expire yes \
\
--hz 10 \
--dynamic-hz yes \
--io-threads 2;
Analisando e rodando testes no container “valkey-db-relax“:
# Analisando
docker inspect valkey-db-relax;
docker diff valkey-db-relax;
docker logs valkey-db-relax;
docker logs -f valkey-db-relax;
# Testar se o container está funcionando:
docker exec -it valkey-db-relax valkey-cli -p 6379 ping;
# Obter terminal valkey-cli:
docker exec -it valkey-db-relax valkey-cli;
6.3 – Container com Persistência em Tempo Real
Container focado em dados persistente sem abrir margem para a perda de nenhuma chave (AOF ativo, sem RDB).
# Rodar valkey-server em container
# - Limite de RAM: 1280 MB
# - Reserva de RAM: 1024 MB
# - Salvando em AOF
# Pasta para salvar dados no volume
mkdir -p /storage/valkey-database;
# Ajuste de permissao na pasta do volume
chown -R 999:999 /storage/valkey-database;
# Renovar/rodar
docker rm -f valkey-database 2>/dev/null;
docker run \
-d --restart=always \
--name valkey-database \
-h valkey-database.intranet.br \
\
--read-only \
--tmpfs /run:rw,noexec,nosuid,size=16m \
\
--cpus=4 \
--memory=1280m \
--memory-swap=1280m \
--memory-reservation=1024m \
--oom-score-adj=-500 \
\
--ulimit nofile=1048576:1048576 \
--ulimit memlock=-1 \
--sysctl net.core.somaxconn=16384 \
\
--network network_public \
\
-v /storage/valkey-database:/data \
-w /data \
\
--health-cmd="valkey-cli -p 6379 ping | grep -q PONG" \
--health-interval=5s \
--health-timeout=3s \
--health-start-period=10s \
--health-retries=3 \
\
valkey/valkey:9.0.3 \
valkey-server \
--bind '0.0.0.0 ::' \
--port 6379 \
--loglevel notice \
--protected-mode no \
--tcp-backlog 4096 \
--timeout 0 \
--tcp-keepalive 30 \
--dir /data \
--dbfilename valkey-database.rdb \
--save "" \
--rdbcompression no \
--rdbchecksum yes \
\
--appendonly yes \
--appendfilename valkey-database.aof \
--appenddirname aof-database \
--appendfsync always \
\
--no-appendfsync-on-rewrite no \
--auto-aof-rewrite-percentage 100 \
--auto-aof-rewrite-min-size 64mb \
--aof-load-truncated yes \
--aof-use-rdb-preamble no \
\
--maxmemory 1024mb \
--maxmemory-policy allkeys-lru \
--maxmemory-samples 5 \
--lazyfree-lazy-eviction yes \
--lazyfree-lazy-expire yes \
\
--hz 10 \
--dynamic-hz yes \
--io-threads 2;
Analisando e rodando testes no container “valkey-database“:
# Analisando
docker inspect valkey-database;
docker diff valkey-database;
docker logs valkey-database;
docker logs -f valkey-database;
# Testar se o container está funcionando:
docker exec -it valkey-database valkey-cli -p 6379 ping;
# Obter terminal valkey-cli:
docker exec -it valkey-database valkey-cli;
7 – Testes de performance
Os testes são importantes para comparar como o Valkey se comporta com cada configuração, cada limite e cada hardware diferente.
Você deve rodar o comando “valkey-benchmark” no mesmo ambiente (HOST ou container) onde está o valyer-server ou informar o IP (descubra em docker inspect).
# Testes de capacidade (loopback test)
# 1 - Testes basicos do Redis
# 1.1 - Use 20 parallel clients, for a total of 100k requests:
valkey-benchmark -h 127.0.0.1 -p 6379 -n 100000 -c 20;
# Summary:
# throughput summary: 44762.76 requests per second
# latency summary (msec):
# avg min p50 p95 p99 max
# 0.240 0.088 0.239 0.271 0.423 1.455
# 1.2 - Fill 127.0.0.1:6379 with about 1 million keys only using the SET test:
valkey-benchmark -t set -n 1000000 -r 100000000;
# Summary:
# throughput summary: 46251.33 requests per second
# latency summary (msec):
# avg min p50 p95 p99 max
# 0.563 0.176 0.559 0.687 0.879 4.247
# 1.3 - Benchmark 127.0.0.1:6379 for a few commands producing CSV output:
valkey-benchmark -t ping,set,get -n 100000 --csv;
# 1.4 - Benchmark a specific command line:
valkey-benchmark -r 10000 -n 10000 eval 'return redis.call("ping")' 0;
# Summary:
# throughput summary: 46511.63 requests per second
# latency summary (msec):
# avg min p50 p95 p99 max
# 0.564 0.160 0.551 0.639 0.887 2.519
# 1.5 - Fill a list with 10000 random elements:
valkey-benchmark -r 10000 -n 10000 lpush mylist __rand_int__;
# Summary:
# throughput summary: 43290.04 requests per second
# latency summary (msec):
# avg min p50 p95 p99 max
# 0.596 0.152 0.575 0.703 0.839 2.327
# 2.0 - Teste realista:
# - 20 mil requisicoes
# - fazer 1.000 requisoes em paralelo
# - criar chaves com valores de 1024 bytes
# - 8 threads de CPU em paralelo
# - pipilene de 8 requisicoes em serie
# - 6 digitos de precisao no resultado
valkey-benchmark \
-h 127.0.0.1 -p 6379 \
-n 20000 -c 1000 \
-d 1024 \
--threads 8 \
-P 8 \
--precision 6;
# Summary:
# throughput summary: 78125.00 requests per second
# latency summary (msec):
# avg min p50 p95 p99 max
# 26.382 2.024 28.655 34.999 48.239 61.807
8 – Configurações Comentadas
Todas as configurações com comentários:
# ==============================================================================
# VALKEY - Arquivo de Configuração
# Compatível com Valkey 7.2+ / 8.x
# Baseado em configuração Redis adaptada para Valkey
# ==============================================================================
# - bind: informa em quais IPs o VALKEY escutará as requisições
# ao configurar apenas IPs de loopback (127.0.0.1 e ::1)
# o VALKEY não abrirá a escuta nos IPs das interfaces de rede
# e estará exclusivo para uso interno do HOST
# Se voce colocar 0.0.0.0 e :: você abrirá o VALKEY em todos
# os IPs e isso requerirá a implementação de autenticação.
bind 127.0.0.1 ::1
# Porta do VALKEY
port 6379
# No modo protegido (yes), se você nao informar mecanismos de autenticação
# o VALKEY não abrirá portas nos IPs das interfaces de rede.
protected-mode yes
# Número de conexões aguardando atendimento
tcp-backlog 511
# Tempo de inatividade antes de fechar a conexão com o cliente, 0=manter pra sempre
timeout 0
# Intervalo entre mensagens de keepalive para manter a conexão ativa,
# importante para impedir a quebra da conexão quando ela atravessa um NAT/CGNAT
tcp-keepalive 30
# Modo daemon, yes para rodar em background (modo HOST),
# no para rodar em foreground (importante no modo DOCKER para segurar o exec)
daemonize yes
# Arquivo para gravar o PID do processo
pidfile /run/valkey/valkey-server.pid
# Nivel de log, opcoes: debug, verbose, notice, warning
loglevel notice
# Arquivo de log para depurar eventos internos e erros
logfile /var/log/valkey/valkey.log
# Total de bases de dados suportadas (de 0 a 15)
# - 16 é o número máximo suportado
databases 16
# Nao exibir mensagem de saudação ao conectar no VALKEY
always-show-logo no
# Alterar argumentos exibidos na lista de processos do Linux
set-proc-title yes
# Formato da nova mensagem de argumentos exibidos na lista de processos do Linux
# opcao util caso você informe a senha no argumento, assim ao modificar
# o argumento a senha deixa de ser exibida na lista de processos.
proc-title-template "{title} {listen-addr} {server-mode}"
#------------------------------------- THREADS DE I/O (exclusivo Valkey)
# O Valkey melhorou significativamente o suporte a multi-threading em relação
# ao Redis original. As threads de I/O permitem que operações de leitura e
# escrita de rede sejam paralelizadas, aumentando o throughput em servidores
# com múltiplos núcleos.
#
# - io-threads: número de threads para processar I/O de rede.
# Use 1 para manter o comportamento single-thread (padrão do Redis legado).
# Para servidores com 4+ núcleos, valores entre 2 e 6 são recomendados.
# ATENÇÃO: não defina mais threads do que núcleos físicos disponíveis.
io-threads 1
# - io-threads-do-reads: habilita o uso das threads de I/O também para
# operações de leitura (além das escritas).
# - yes habilita leitura multi-thread (maior throughput em cargas mistas)
# - no reserva as threads apenas para escritas (padrão mais conservador)
io-threads-do-reads no
#------------------------------------- SEGURANÇA DE DADOS
# Modo de segurança de dados: ao colocar como yes o VALKEY para
# de aceitar novas escritas se as rotinas que salvam os dados
# no disco derem erro
stop-writes-on-bgsave-error yes
#------------------------------------- RDB - Salvamento de dados
# Ativar compressao de dados:
# - yes ativa compressão LZF (levemente mais lento, ocupa menos espaço em disco)
# - no grava os dados sem compressão (mais rápido mas ocupa mais espaço em disco)
rdbcompression yes
# Inserir checksum para impedir/detectar corrupção de registros no armazenamento
# - yes ajuda a evitar corrupções e panes entre restarts acidentais
# - no ajuda a deixar o salvamento em disco mais rápido, porem mais sensível a
# danos.
rdbchecksum yes
# Arquivo em disco onde as chaves de RAM serão salvas
dbfilename valkey_6379_dump.rdb
# Deletar arquivo RDB danificado?
# - yes para deletar arquivos corrompidos e continuar sem eles,
# - no para manter o arquivo para analise e recuperações
# caso os dados sejam importantes
rdb-del-sync-files no
# Pasta onde os arquivos RDB serão gravados, prefira
# sempre informar uma pasta montada em um sistema de alta velocidade
# como SSD/NVME
dir /var/lib/valkey/
#------------------------------------- AOF - Salvamento de dados
# Ativar modo AOF?
# - yes ativa o registro de todas as operações para recuperação exata
# - no deixa o modo AOF desativado (padrão)
appendonly no
# Arquivo de registro de todas operações
appendfilename "appendonly.aof"
# Sub-diretório onde os arquivos de AOF serão gravados no disco
# Esse diretório ficará dentro da pasta definida na config [dir]
# por padrão em: /var/lib/valkey/ + [appenddirname]
# Caminho final: /var/lib/valkey/appendonlydir/
appenddirname "appendonlydir"
# Frequencia de gravação das operações no AOF por meio de um pedido
# de sync() ao sistema operacional.
# - everysec: de 1 em 1 segundo (equilíbrio entre desempenho e segurança)
# - always: sempre que houver qualquer gravação de chaves ou expiração
# (máxima segurança, menor desempenho)
# - no: deixar que o sistema operacional decida quando efetivar a escrita atrasada
# (maior desempenho, maior risco de perda de dados)
appendfsync everysec
# Controlar se haverá pause na sincronização do AOF
# durante uma reescrita do arquivo.
# - yes pausa a sincronizacao durante reescritas, melhor desempenho mas
# abre a possibilidade da perda de dados se o servidor VALKEY
# for desligado da energia durante a reescrita
# - no faz com que a reescrita não pause a chamada do sync() ao sistema operacional
# durante as reescritas
no-appendfsync-on-rewrite no
# Percentual de crescimento do AOF para disparar uma reescrita automática.
# Quando o arquivo AOF crescer X% em relação ao tamanho que tinha após
# a última reescrita, uma nova reescrita é acionada.
# - 100 significa que o arquivo precisa dobrar de tamanho para acionar a reescrita
# - 0 desativa a reescrita automática por crescimento percentual
auto-aof-rewrite-percentage 100
# Tamanho mínimo que o arquivo AOF precisa ter para que a reescrita automática
# seja acionada. Impede reescritas frequentes quando o arquivo ainda é pequeno.
auto-aof-rewrite-min-size 64mb
# Aceitar arquivos AOF truncados (incompletos) na inicialização?
# - yes carrega os dados disponíveis e ignora o final truncado
# (útil após falhas de energia no meio de uma escrita)
# - no recusa o arquivo truncado e exige intervenção manual
aof-load-truncated yes
# Usar preâmbulo RDB no arquivo AOF?
# - yes grava um snapshot RDB no início do AOF, acelerando o carregamento
# inicial pois não precisa replayer todas as operações desde o início
# - no grava apenas os comandos AOF puros
aof-use-rdb-preamble yes
# Registrar timestamp em cada entrada AOF?
# - yes adiciona marcação temporal nas entradas (útil para PITR - Point-in-Time Recovery)
# - no mantém o formato padrão sem timestamps
# ATENÇÃO: ao ativar, o arquivo AOF não será compatível com versões
# mais antigas do Redis/Valkey que não suportam timestamps
aof-timestamp-enabled no
#------------------------------------- REPLICAÇÃO
# Permitir que réplicas respondam requisições com dados potencialmente
# desatualizados enquanto estão sincronizando com o primário?
# - yes permite leitura de dados defasados (maior disponibilidade)
# - no retorna erro enquanto a réplica não está sincronizada (maior consistência)
replica-serve-stale-data yes
# Réplicas aceitam apenas leitura?
# - yes impede escritas diretas na réplica (recomendado)
# - no permite escritas diretas (pode causar divergência de dados)
replica-read-only yes
# Usar transferência RDB sem disco ao sincronizar réplicas?
# - yes o primário transmite o RDB diretamente pela rede (sem gravar em disco)
# ideal para SSDs com escrita limitada ou muitas réplicas simultâneas
# - no grava o RDB em disco antes de enviar à réplica (modo clássico)
repl-diskless-sync yes
# Tempo de espera (em segundos) antes de iniciar a sincronização diskless,
# permitindo que mais réplicas se conectem e recebam o mesmo RDB simultaneamente
repl-diskless-sync-delay 5
# Número máximo de réplicas que receberão a sincronização diskless simultânea.
# - 0 sem limite (aguarda apenas o delay acima)
repl-diskless-sync-max-replicas 0
# Modo de carregamento diskless na réplica:
# - disabled a réplica grava o RDB em disco antes de carregá-lo (padrão seguro)
# - on-empty-db carrega diretamente na memória apenas se a réplica estiver vazia
# - swapdb troca o banco em memória diretamente (experimental, risco de OOM)
repl-diskless-load disabled
# Desativar o algoritmo Nagle (TCP_NODELAY) na conexão de replicação?
# - no mantém TCP_NODELAY desativado: envia pacotes imediatamente,
# menor latência de replicação mas maior uso de banda
# - yes ativa agrupamento de pacotes (Nagle): menor uso de banda,
# maior latência de replicação
repl-disable-tcp-nodelay no
# Prioridade da réplica para eleição como primário (menor = maior prioridade).
# - 0 impede que a réplica seja promovida a primário
replica-priority 100
#------------------------------------- ACL (Controle de Acesso)
# Tamanho máximo do log de tentativas de acesso via ACL
acllog-max-len 128
#------------------------------------- LIBERAÇÃO PREGUIÇOSA (LAZY FREE)
# Operações de deleção em memória podem bloquear o servidor quando
# envolvem estruturas muito grandes. O modo lazy free executa a liberação
# de memória em background, evitando travamentos.
# Liberar memória em background durante evicção por política de memória cheia?
# - yes evita travamentos durante evicção (recomendado com maxmemory ativo)
# - no deleta sincronicamente (pode travar por milissegundos)
lazyfree-lazy-eviction no
# Liberar chaves expiradas em background?
# - yes processa expirações de forma assíncrona
# - no processa expirações sincronamente
lazyfree-lazy-expire no
# Usar lazy free para deleções internas do servidor (ex: substituição de chaves)?
# - yes proteção contra travamentos em deleções implícitas
# - no comportamento síncrono padrão
lazyfree-lazy-server-del no
# Usar lazy free ao limpar base de dados de uma réplica durante sincronização?
# - yes evita bloqueio durante FLUSHALL em sincronização de réplica
# - no limpa a base de forma síncrona
replica-lazy-flush no
# Usar lazy free para comandos DEL explícitos do usuário?
# - yes faz DEL se comportar como UNLINK (assíncrono)
# - no mantém DEL síncrono (padrão compatível)
lazyfree-lazy-user-del no
# Usar lazy free para comandos FLUSHALL/FLUSHDB do usuário?
# - yes torna o FLUSH assíncrono
# - no FLUSH síncrono (padrão)
lazyfree-lazy-user-flush no
#------------------------------------- OOM SCORE ADJUSTMENT
# Ajuste da pontuação OOM (Out-Of-Memory Killer) do Linux para os processos
# do Valkey. Valores maiores = maior chance de ser encerrado pelo kernel
# em situação de falta de memória.
# - no não ajusta as pontuações OOM (padrão)
# - yes ajusta usando os valores abaixo
# - absolute define os valores diretamente (sem considerar o valor atual)
oom-score-adj no
# Pontuações OOM para: [server] [replica] [background-child]
# - server: processo principal (0 = nunca matar, ideal para primário)
# - replica: processo de réplica (200 = baixa prioridade de proteção)
# - background-child: processo de bgsave/bgrewrite (800 = sacrificável primeiro)
oom-score-adj-values 0 200 800
# Desativar Transparent Huge Pages (THP)?
# - yes desativa THP, reduzindo latência e uso de memória em processos fork
# (RECOMENDADO para produção)
# - no mantém THP ativado pelo kernel (pode causar picos de latência)
disable-thp yes
#------------------------------------- SLOW LOG
# Registrar comandos que demorem mais que X microsegundos (10000 = 10ms).
# Use -1 para desativar, 0 para registrar todos os comandos.
slowlog-log-slower-than 10000
# Número máximo de entradas mantidas no slow log
slowlog-max-len 128
#------------------------------------- MONITORAMENTO DE LATÊNCIA
# Limite em milissegundos para registrar eventos de latência.
# - 0 desativa o monitoramento de latência
# - Ex: 100 registra eventos com latência acima de 100ms
latency-monitor-threshold 0
#------------------------------------- NOTIFICAÇÕES DE KEYSPACE
# Habilitar notificações de eventos de keyspace via Pub/Sub.
# String de configuração com combinação de letras:
# K = notificações de keyspace (__keyspace@<db>__)
# E = notificações de keyevent (__keyevent@<db>__)
# g = comandos genéricos (DEL, EXPIRE, RENAME...)
# $ = comandos de string
# l = comandos de list
# s = comandos de set
# h = comandos de hash
# z = comandos de sorted set
# x = eventos de expiração
# d = eventos de módulo
# t = comandos de stream
# m = eventos de miss de chave (quando uma chave não existe)
# A = atalho para todos os eventos (exceto m)
# Ex: "KEA" ativa notificações completas de keyspace e keyevent
# "" desativa todas as notificações (padrão, sem custo de CPU)
notify-keyspace-events ""
#------------------------------------- OTIMIZAÇÕES DE ESTRUTURA DE DADOS
# O Valkey usa representações compactas (listpack/ziplist) para estruturas
# pequenas, economizando memória. Acima dos limites abaixo, converte para
# a estrutura completa (hashtable, skiplist, etc.)
# Hash: limite para uso de listpack (compacto)
hash-max-listpack-entries 512
hash-max-listpack-value 64
# List: limite de tamanho por nó interno
# Valores negativos são limites em bytes: -1=4KB, -2=8KB, -3=16KB, -4=32KB, -5=64KB
list-max-listpack-size -2
# Compressão de nós internos da lista (0 = sem compressão)
# Ex: 1 comprime todos exceto o primeiro e o último nó
list-compress-depth 0
# Set de inteiros: limite para usar intset (compacto)
set-max-intset-entries 512
# Sorted Set: limite para uso de listpack (compacto)
zset-max-listpack-entries 128
zset-max-listpack-value 64
# HyperLogLog: limite para usar representação esparsa (compacta)
hll-sparse-max-bytes 3000
# Stream: limites por nó interno da estrutura de stream
stream-node-max-bytes 4096
stream-node-max-entries 100
#------------------------------------- DESEMPENHO GERAL
# Rehashar tabelas de hash em background de forma ativa?
# - yes redistribui buckets gradualmente entre operações (recomendado)
# - no aguarda pressão de memória para rehash
activerehashing yes
# Limites do buffer de saída por tipo de cliente:
# Formato: [tipo] [hard-limit] [soft-limit] [soft-seconds]
# - hard-limit: desconecta imediatamente ao atingir
# - soft-limit + soft-seconds: desconecta se permanecer acima por X segundos
# - 0 = sem limite
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
# Frequência base do loop de eventos do servidor (operações por segundo).
# - Controla timers internos: expiração de chaves, reconexões, etc.
# - Valores entre 1 e 500; padrão 10 é adequado para maioria dos casos
hz 10
# Ajuste dinâmico do hz conforme número de clientes conectados?
# - yes aumenta o hz automaticamente quando há mais clientes ativos,
# reduzindo latência em momentos de alta carga
# - no mantém hz fixo conforme configurado acima
dynamic-hz yes
# Sincronização incremental ao reescrever arquivo AOF?
# - yes sincroniza a cada 32MB durante reescrita, evitando picos de I/O
# - no sincroniza tudo ao final (pode causar stall de disco em arquivos grandes)
aof-rewrite-incremental-fsync yes
# Sincronização incremental ao salvar arquivo RDB?
# - yes sincroniza a cada 32MB durante o bgsave, evitando picos de I/O
# - no sincroniza tudo ao final
rdb-save-incremental-fsync yes
# Usar thread em background para desfragmentação do alocador jemalloc?
# - yes reduz uso de memória física ao longo do tempo (recomendado)
# - no desativa a desfragmentação em background
jemalloc-bg-thread yes
.
“A rapidez, que é uma virtude,
gera um vício, que é a pressa.“
Gregório Marañón
Terminamos por hoje!
Patrick Brandão, patrickbrandao@gmail.com
