Banco de Dados Chave‑Valor com Valkey
O perfil Chave‑Valor é indicado quando os dados fazem parte do estado da aplicação e não podem ser tratados como simples resultados descartáveis. A capacidade de armazenamento é persistente e o plano comercial usa os produtos db-*.
Operações recomendadas
Use prefixos por domínio e defina TTL apenas quando o dado realmente expirar. NX é útil para criação condicional e locks curtos, mas locks de produção precisam de token único, expiração e liberação segura.
SET session:{user-id} <json> EX 3600
GET session:{user-id}
MSET profile:{user-id} <json> flags:{user-id} <json>
SET lock:{resource} <unique-token> NX EX 30Não use KEYS * em produção. Prefira SCAN com limite de trabalho e mantenha o tamanho dos valores sob controle.
Node.js e TypeScript
npm install iovalkeyimport Redis from 'iovalkey'
import { randomUUID } from 'node:crypto'
const source = process.env.VALKEY_URL
if (!source) throw new Error('VALKEY_URL is required')
const url = new URL(source)
const client = new Redis({
host: url.hostname,
port: Number(url.port),
username: decodeURIComponent(url.username),
password: decodeURIComponent(url.password),
tls: { servername: url.hostname },
})
await client.set('session:user-42', JSON.stringify({ role: 'admin' }), 'EX', 3600)
const session = await client.get('session:user-42')
const created = await client.set('lock:invoice-42', randomUUID(), 'NX', 'EX', 30)
console.log({ session, lockCreated: created === 'OK' })
await client.quit()Python
python -m pip install valkeyimport json
import os
import uuid
from urllib.parse import urlparse
from valkey import Valkey
url = urlparse(os.environ["VALKEY_URL"])
client = Valkey(
host=url.hostname, port=url.port, username=url.username, password=url.password,
ssl=True, ssl_check_hostname=True, decode_responses=True,
)
client.set("session:user-42", json.dumps({"role": "admin"}), ex=3600)
session = client.get("session:user-42")
token = str(uuid.uuid4())
lock_created = client.set("lock:invoice-42", token, nx=True, ex=30)
print({"session": session, "lock_created": lock_created})
client.close()Consistência e limites
- Faça operações relacionadas em uma transação ou script quando elas precisarem ser atômicas.
- Torne escritas e retries idempotentes; uma resposta de rede perdida não informa se o servidor aplicou a operação.
- Não trate o perfil como banco relacional: não há joins, constraints ou consultas ad hoc.
- Planeje a capacidade para chaves, valores, índices da aplicação e margem de crescimento.
- Use o plano Cache quando o dado puder ser reconstruído; não use Chave‑Valor apenas para aproveitar o armazenamento.
Padrões recomendados
Use namespaces por domínio, como session:, lock: e counter:, para facilitar inspeção e invalidação seletiva. Defina limites de tamanho para valores serializados e prefira estruturas nativas quando elas reduzirem a duplicação. Para contadores, INCRBY é atômico no servidor; para vários campos relacionados, um script Lua ou transação pode manter a operação consistente.
Locks devem ter TTL e um token único. Ao liberar um lock, compare o token no servidor para não remover o lock de outro worker que o assumiu depois de uma expiração. Sessões devem ter expiração compatível com o ciclo de autenticação e uma estratégia clara para renovar o TTL. Em retries, use chaves de idempotência para que uma requisição repetida não crie efeitos duplicados.
O perfil Chave‑Valor não substitui um banco relacional: consultas ad hoc, joins e relatórios devem continuar no sistema apropriado. Faça backup lógico dos dados realmente importantes na aplicação e teste a restauração; persistência da instância não elimina a necessidade de uma política de recuperação.