Comprendiendo el Espacio de Claves de Redis: Comandos de Eliminación e Inspección
Descubre el poder de la gestión del espacio de claves de Redis con esta guía completa. Aprende a inspeccionar tus datos de forma segura usando `SCAN` (y por qué evitar `KEYS` en producción) y a eliminar claves eficientemente con `DEL` y el no bloqueante `UNLINK`. Comprende la naturaleza destructiva de `FLUSHDB` y `FLUSHALL` y descubre las mejores prácticas para mantener una instancia de Redis saludable y de alto rendimiento.
Comprendiendo el Espacio de Claves de Redis: Comandos de Eliminación e Inspección
El espacio de claves de Redis es simplemente el conjunto de claves en la base de datos actualmente seleccionada, pero la forma en que inspeccionas y eliminas esas claves puede decidir si una limpieza es aburrida o si tu aplicación se detiene en medio del tráfico.
La mayoría de los equipos aprenden esto de la manera difícil. Alguien necesita eliminar las claves session:* de un caché de staging, ejecuta KEYS session:*, ve la lista, y luego intenta el mismo hábito en producción. En una base de datos pequeña, eso se siente bien. En una instancia ocupada con millones de claves, el comando puede retener el servidor el tiempo suficiente para que solicitudes no relacionadas se pongan en cola detrás de él. Redis procesa comandos muy rápidamente, pero un comando que recorre todo el espacio de claves aún tiene que hacer el trabajo.
Para operaciones diarias, piensa en dos pasos separados: encuentra las claves de forma segura, luego elimínalas de forma segura. No trates la inspección de claves como una lectura inofensiva. Un comando de lectura aún puede ser costoso.
Comienza con la base de datos que realmente estás usando
Antes de eliminar algo, confirma el endpoint y la base de datos lógica.
redis-cli -h redis.example.internal -p 6379 INFO keyspace
La salida se ve así:
# Keyspace
db0:keys=154233,expires=129900,avg_ttl=2851412
db2:keys=32,expires=32,avg_ttl=60000
Eso te dice qué bases de datos lógicas contienen claves. Muchas implementaciones de Redis solo usan la base de datos 0. Redis Cluster solo admite la base de datos 0, por lo que FLUSHDB y FLUSHALL merecen cuidado adicional allí porque el modelo mental habitual de "base de datos seleccionada" no es útil de la misma manera.
Si tu aplicación usa bases de datos numeradas en Redis independiente, selecciona la correcta explícitamente:
redis-cli -n 2 DBSIZE
DBSIZE devuelve el número de claves en la base de datos seleccionada. No muestra nombres, y no reemplaza un pase de inspección, pero es una buena verificación de cordura antes y después de la limpieza.
Usa KEYS solo cuando el espacio de claves es pequeño y desechable
KEYS pattern devuelve cada clave que coincide con un patrón de estilo glob:
KEYS user:*
KEYS cache:product:???
KEYS *
Las reglas de patrón son útiles: * coincide con cualquier secuencia, ? coincide con un carácter, y los rangos entre corchetes como [0-9] coinciden con un carácter del rango.
El problema no es la corrección. El problema es que KEYS escanea todo el espacio de claves en un solo comando. En un Redis de desarrollo local con unos pocos cientos de claves, eso es conveniente. En un caché compartido, puede agregar latencia para cada otro cliente mientras Redis está ocupado produciendo el resultado. El comando está documentado como un comando de espacio de claves con complejidad lineal, por lo que no debería ser parte de los scripts de limpieza de producción normales.
Todavía uso KEYS en dos lugares:
- Un Redis local desechable mientras escribo pruebas.
- Una base de datos de staging pequeña donde ya he verificado
DBSIZEy sé que el comando no puede sorprenderme.
En todos los demás lugares, usa SCAN.
Usa SCAN para inspección en producción
SCAN está basado en cursor:
SCAN 0 MATCH user:* COUNT 100
Redis devuelve dos cosas: el siguiente cursor y un lote de claves. Comienza en el cursor 0. Sigue escaneando con el cursor devuelto. Detente cuando Redis devuelva el cursor 0 nuevamente.
1) "24576"
2) 1) "user:100"
2) "user:101"
COUNT es una sugerencia, no una promesa. Redis puede devolver más claves, menos claves, o incluso ninguna clave para una iteración dada. MATCH filtra lo que regresa, pero Redis aún avanza a través del espacio de claves. Un patrón estrecho es útil para reducir el trabajo del lado del cliente, pero no hace que cada escaneo sea gratuito mágicamente.
Para trabajo en shell, prefiere redis-cli --scan porque oculta el bucle del cursor:
redis-cli --scan --pattern 'session:*'
Para contar las claves coincidentes sin imprimirlas todas:
redis-cli --scan --pattern 'session:*' | wc -l
Para inspeccionar tipos antes de eliminar:
redis-cli --scan --pattern 'session:*' | head
redis-cli TYPE session:abc123
redis-cli TTL session:abc123
redis-cli MEMORY USAGE session:abc123
TTL es especialmente útil para decisiones de limpieza. Si un espacio de nombres de caché ya tiene expiraciones razonables, es posible que no necesites una eliminación masiva en absoluto. Dejar que las claves expiren naturalmente suele ser menos arriesgado que forzar una gran eliminación durante el horario laboral.
Elimina claves conocidas con DEL
DEL elimina una o más claves y devuelve cuántas existían:
DEL session:abc123
DEL session:abc123 session:def456 session:ghi789
Para claves pequeñas, DEL suele estar bien. Eliminar una clave de cadena o un hash pequeño no es el caso aterrador. El caso que duele es eliminar un valor agregado grande, como una lista con una gran cantidad de elementos, un conjunto usado como índice, o un hash que creció mucho más allá de su propósito original. Redis elimina la clave del espacio de claves, pero liberar un valor grande puede costar tiempo en la ruta principal.
Si estás eliminando una clave que sabes que es pequeña, usa DEL. Si estás eliminando muchas claves o no estás seguro de qué tan grandes son, usa UNLINK.
Prefiere UNLINK para eliminación grande o masiva
UNLINK tiene la misma forma que DEL:
UNLINK session:abc123
UNLINK cache:old:1 cache:old:2 cache:old:3
La diferencia importante es la recuperación de memoria. UNLINK elimina las claves del espacio de claves inmediatamente, luego libera la memoria de forma asíncrona. Eso lo convierte en un valor predeterminado más seguro cuando estás limpiando claves que podrían contener valores grandes.
Esto no significa que UNLINK sea mágico. Aún puedes crear presión si tu script descubre y desvincula millones de claves lo más rápido posible. Redis aún tiene que procesar los comandos, las réplicas aún necesitan recibir los cambios, y la memoria aún tiene que ser recuperada. Regula la limpieza masiva para que puedas observar la latencia y la memoria mientras se ejecuta.
Un bucle de limpieza práctico se ve así:
redis-cli --scan --pattern 'session:*' |
xargs -r -L 100 redis-cli UNLINK
Eso elimina en lotes de 100 claves. Ajusta el tamaño del lote para tu entorno. En una ventana de mantenimiento tranquila, podrías usar lotes más grandes. En un caché caliente compartido por tráfico orientado al usuario, lotes más pequeños más un breve sueño entre lotes pueden ser más amables:
redis-cli --scan --pattern 'session:*' |
while read -r key; do
redis-cli UNLINK "$key" >/dev/null
sleep 0.005
done
Esa versión es más lenta, pero es fácil de detener y fácil de razonar.
Ten cuidado con las eliminaciones por patrón
Redis intencionalmente no proporciona DEL user:*. Tienes que combinar el escaneo y la eliminación tú mismo. Esa fricción es útil porque las eliminaciones por patrón son donde ocurren los accidentes.
Antes de eliminar:
redis-cli --scan --pattern 'user:*' | head -50
redis-cli --scan --pattern 'user:*' | wc -l
Mira la primera muestra. Cuenta el tamaño objetivo. Si tu limpieza esperada era "unos pocos miles de sesiones abandonadas" y el conteo es "la mayor parte de la base de datos", detente y corrige el patrón.
Usa convenciones de nomenclatura que hagan la limpieza aburrida:
app:prod:session:<id>
app:prod:rate-limit:<user-id>
app:prod:cache:product:<id>
Eso es más verboso que session:<id>, pero te permite apuntar a un espacio de nombres con precisión. En Redis Cluster, los nombres de las claves también pueden incluir etiquetas hash como cart:{user123}:items para la ubicación de los slots. Ten en cuenta esas convenciones antes de escribir patrones amplios.
FLUSHDB y FLUSHALL son botones de reinicio
FLUSHDB elimina todas las claves de la base de datos seleccionada:
FLUSHDB
FLUSHDB ASYNC
FLUSHALL elimina todas las claves de todas las bases de datos lógicas:
FLUSHALL
FLUSHALL ASYNC
Redis moderno admite modificadores ASYNC y SYNC para los comandos de vaciado. ASYNC programa la liberación en segundo plano, lo que ayuda a evitar una gran pausa síncrona de liberación de memoria. No hace que la operación sea reversible. Una vez que las claves desaparecen del espacio de claves, tu aplicación las ve como desaparecidas.
Antes de usar cualquiera de los comandos, quiero tres verificaciones:
redis-cli ROLE
redis-cli INFO keyspace
redis-cli CONFIG GET dir
ROLE ayuda a confirmar si estás conectado a un primario o una réplica. INFO keyspace muestra lo que se verá afectado. CONFIG GET dir a menudo da otra pista sobre en qué instancia estás, porque los directorios de datos tienden a incluir rutas específicas del entorno.
Para scripts de reinicio de desarrollo, sé explícito:
redis-cli -h 127.0.0.1 -p 6379 -n 0 FLUSHDB ASYNC
Evita scripts que ejecuten redis-cli FLUSHALL con valores predeterminados. Los valores predeterminados cambian cuando un script se ejecuta en otro host, en otro contenedor, o desde un ejecutor de CI con diferentes variables de entorno.
Verifica después de la eliminación
Después de una limpieza, verifica tanto el conteo como el comportamiento de la aplicación:
redis-cli --scan --pattern 'session:*' | wc -l
redis-cli INFO memory
redis-cli INFO stats | grep expired_keys
La memoria puede no caer instantáneamente después de UNLINK o un vaciado asíncrono porque la liberación ocurre en segundo plano y los asignadores pueden mantener la memoria reservada para reutilización. Eso no es automáticamente una fuga. Observa used_memory, la latencia, y si el conteo de claves se mueve en la dirección que esperas.
Para cambios en producción, anota el comando exacto y el patrón antes de ejecutarlo. Una limpieza segura de Redis no es solo el comando correcto. Es el comando correcto, contra la instancia correcta, con un patrón que has muestreado, durante una ventana donde puedas observar el resultado.
Un runbook de limpieza de producción más seguro
Para una limpieza real, me gusta convertir el comando en un pequeño runbook en lugar de un one-liner escrito de memoria. El runbook no necesita ser elegante. Debe responder cuatro preguntas: qué instancia, qué patrón, cuántas claves, y qué tan rápido.
Comienza con verificaciones de solo lectura:
redis-cli -h redis.example.internal -p 6379 ROLE
redis-cli -h redis.example.internal -p 6379 INFO keyspace
redis-cli -h redis.example.internal -p 6379 --scan --pattern 'app:prod:session:*' | head -20
redis-cli -h redis.example.internal -p 6379 --scan --pattern 'app:prod:session:*' | wc -l
Luego inspecciona algunas claves representativas:
redis-cli TYPE app:prod:session:sample
redis-cli TTL app:prod:session:sample
redis-cli MEMORY USAGE app:prod:session:sample
Si la muestra muestra claves que deberían expirar naturalmente en unos minutos, espera en lugar de eliminar. Si las claves no tienen TTL y claramente pertenecen a datos abandonados, procede con una limpieza regulada. Mantén una terminal abierta con latencia o memoria:
redis-cli --latency
redis-cli INFO memory
Para Redis de producción compartido, prefiero un script que se pueda detener sin perder el rastro de la intención:
redis-cli --scan --pattern 'app:prod:session:*' |
while read -r key; do
redis-cli UNLINK "$key" >/dev/null
sleep 0.002
done
Esa no es la versión más rápida. Es la versión que te da la oportunidad de notar si la latencia se mueve, los clientes se quejan, o el patrón era más amplio de lo esperado. Cuando la instancia está tranquila y el conteo es modesto, el procesamiento por lotes con xargs -L 100 está bien. El punto es elegir el ritmo intencionalmente.
Un hábito más ayuda: guarda el conteo antes y después en el ticket de incidente o nota de implementación. "Claves de sesión eliminadas" no es suficiente. "Eliminadas 48,213 claves que coinciden con app:prod:session:* de db0 en redis-cache-01 usando UNLINK, no se observó aumento de latencia" es el tipo de nota que ahorra tiempo después.