← Volver al listado de tecnologías

Rendimiento en Valkey

Por: Artiko
valkeyrendimientooptimizacionbenchmarkmemoria

Rendimiento

Benchmark integrado

# Benchmark básico
valkey-benchmark

# Opciones comunes
valkey-benchmark -h localhost -p 6379 -c 50 -n 100000

# Parámetros:
# -c: clientes concurrentes (default 50)
# -n: número de requests (default 100000)
# -d: tamaño de datos en bytes (default 3)
# -t: comandos específicos
# -q: modo silencioso (solo resultados)

# Solo ciertos comandos
valkey-benchmark -t SET,GET,INCR -q

# Con pipeline
valkey-benchmark -P 16 -q

Resultados típicos

SET: 125000.00 requests per second
GET: 145000.00 requests per second
INCR: 150000.00 requests per second
LPUSH: 140000.00 requests per second
LPOP: 145000.00 requests per second

Optimización de memoria

Configuración de memoria

# valkey.conf

# Límite de memoria
maxmemory 2gb

# Política de evicción
maxmemory-policy allkeys-lru

# Opciones:
# noeviction      - Error si se llena
# allkeys-lru     - Eliminar menos usados
# volatile-lru    - LRU solo en claves con TTL
# allkeys-random  - Eliminar aleatorio
# volatile-random - Aleatorio solo con TTL
# volatile-ttl    - Eliminar los que expiran pronto

Monitoreo de memoria

# Info de memoria
INFO memory

# Métricas importantes:
# used_memory: memoria usada
# used_memory_peak: pico máximo
# mem_fragmentation_ratio: fragmentación

# Memoria por clave
MEMORY USAGE mi_clave

# Estadísticas de claves
MEMORY STATS

# Análisis de claves grandes
valkey-cli --bigkeys

Optimización de estructuras

# Hashes pequeños son más eficientes
# Configurar umbrales
hash-max-listpack-entries 512
hash-max-listpack-value 64

# Listas
list-max-listpack-size -2

# Sets
set-max-listpack-entries 128
set-max-listpack-value 64

# Sorted Sets
zset-max-listpack-entries 128
zset-max-listpack-value 64

Pipeline

Reduce latencia agrupando comandos:

# Sin pipeline: N round-trips
GET clave1
GET clave2
GET clave3

# Con pipeline: 1 round-trip
(echo "GET clave1"; echo "GET clave2"; echo "GET clave3") | valkey-cli

Python con pipeline

import valkey

r = valkey.Valkey()

# Sin pipeline (lento)
for i in range(1000):
    r.set(f'clave:{i}', f'valor:{i}')

# Con pipeline (rápido)
pipe = r.pipeline()
for i in range(1000):
    pipe.set(f'clave:{i}', f'valor:{i}')
pipe.execute()

Node.js con pipeline

// Multi-exec actúa como pipeline
const results = await client.multi()
    .set('a', '1')
    .set('b', '2')
    .set('c', '3')
    .exec();

Conexiones

Pool de conexiones

# Python con pool
pool = valkey.ConnectionPool(
    host='localhost',
    port=6379,
    max_connections=20,
    decode_responses=True
)

r = valkey.Valkey(connection_pool=pool)
// Node.js - socket pooling automático
const client = createClient({
    socket: {
        connectTimeout: 5000,
        keepAlive: 5000
    }
});

Configuración del servidor

# valkey.conf

# Máximo de clientes
maxclients 10000

# Timeout de inactividad
timeout 300

# TCP keepalive
tcp-keepalive 300

Comandos costosos

Evitar KEYS

# MAL: escanea todas las claves
KEYS user:*

# BIEN: iterativo
SCAN 0 MATCH user:* COUNT 100

Usar SCAN

def scan_keys(pattern):
    cursor = 0
    while True:
        cursor, keys = r.scan(cursor, match=pattern, count=100)
        for key in keys:
            yield key
        if cursor == 0:
            break

for key in scan_keys('user:*'):
    print(key)

Evitar comandos O(N)

# Costosos en colecciones grandes:
SMEMBERS set_grande      # Usar SSCAN
HGETALL hash_grande      # Usar HSCAN
LRANGE lista 0 -1        # Usar paginación

# Mejor:
SSCAN set_grande 0 COUNT 100
HSCAN hash_grande 0 COUNT 100
LRANGE lista 0 99

Configuración de CPU

# valkey.conf

# Threads para I/O (Valkey 7+)
io-threads 4
io-threads-do-reads yes

# Afinidad de CPU (si es necesario)
# Usar taskset al iniciar
# Iniciar con afinidad de CPU
taskset -c 0-3 valkey-server valkey.conf

Lazy freeing

# Liberar memoria en background
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
lazyfree-lazy-server-del yes

# UNLINK en lugar de DEL para colecciones grandes
replica-lazy-flush yes
# Eliminar clave grande sin bloquear
UNLINK coleccion_grande

# En lugar de
DEL coleccion_grande

Monitoreo de latencia

# Latencia continua
valkey-cli --latency

# Historial de latencia
valkey-cli --latency-history

# Distribución de latencia
valkey-cli --latency-dist

# Latencia intrínseca del sistema
valkey-cli --intrinsic-latency 10

Slow log

# Configurar (microsegundos)
CONFIG SET slowlog-log-slower-than 10000
CONFIG SET slowlog-max-len 128

# Ver comandos lentos
SLOWLOG GET 10

# Resetear
SLOWLOG RESET

Script de optimización

#!/bin/bash
# optimize_check.sh

echo "=== Análisis de rendimiento ==="

# Memoria
echo -e "\n--- Memoria ---"
valkey-cli INFO memory | grep -E "(used_memory_human|mem_fragmentation)"

# Clientes
echo -e "\n--- Clientes ---"
valkey-cli INFO clients | grep -E "(connected|blocked)"

# Estadísticas
echo -e "\n--- Stats ---"
valkey-cli INFO stats | grep -E "(ops_per_sec|keyspace_hits|keyspace_misses)"

# Hit ratio
HITS=$(valkey-cli INFO stats | grep keyspace_hits | cut -d: -f2)
MISSES=$(valkey-cli INFO stats | grep keyspace_misses | cut -d: -f2)
TOTAL=$((HITS + MISSES))
if [ $TOTAL -gt 0 ]; then
    RATIO=$(echo "scale=2; $HITS * 100 / $TOTAL" | bc)
    echo "Hit ratio: $RATIO%"
fi

# Comandos lentos
echo -e "\n--- Slow Log ---"
valkey-cli SLOWLOG GET 5

Checklist de rendimiento

AspectoVerificar
PipelineUsar para operaciones múltiples
SCANEn lugar de KEYS
TTLEn claves temporales
Memoriamaxmemory y política configurados
ConexionesPool de conexiones
DatosEstructuras apropiadas

Ejercicios

  1. Ejecuta benchmarks y optimiza configuración
  2. Implementa pipeline para operaciones batch
  3. Crea un script de monitoreo de rendimiento

Resumen