Saltar al contenido

Capítulo 9 de 13

Memoria, permisos y límites entre aplicaciones

Evitar expulsar trabajos, limitar el impacto de credenciales y distinguir organización de claves de aislamiento real.

#La RAM es un presupuesto, no una impresión

Redis conserva datos de trabajo en memoria, pero el proceso consume más que el tamaño de tus valores: hay metadatos, conexiones, buffers, estructuras internas y fragmentación. Una fotografía o reescritura puede necesitar memoria adicional por copia al escribir mientras el hijo guarda datos. Un maxmemory igual al límite del contenedor deja demasiado poco margen para esas tareas.

Empieza midiendo valores representativos con MEMORY USAGE, número de claves y distribución de tamaños. Calcula una aproximación: entidades activas por bytes medios, más margen para claves, picos, buffers y persistencia. Después verifica el RSS real del proceso y los picos durante backups. El tamaño del JSON en el disco no equivale a la RAM exacta del servidor.

#Expiración y expulsión son decisiones diferentes

La expiración elimina una clave cuando vence su TTL. La expulsión, o eviction, retira claves para liberar memoria según una política. Una clave con TTL de una hora puede desaparecer mucho antes si la política permite expulsarla. Tu aplicación debe tolerarlo en una caché; no debe asumir que un trabajo pendiente disfruta de esa misma tolerancia.

Política Comportamiento Cuándo tiene sentido
allkeys-lru Prefiere expulsar claves menos usadas recientemente, de forma aproximada Caché general reconstruible
allkeys-lfu Prefiere claves menos frecuentes, con estimación y envejecimiento Conjunto con popularidad muy desigual
volatile-* Considera solo claves con TTL para expulsar Mezcla deliberada, con límites y riesgos entendidos
noeviction Rechaza ciertas escrituras al alcanzar el límite Trabajos o coordinación que no pueden desaparecer arbitrariamente

noeviction no garantiza que nunca falte memoria: errores, buffers y límites del host siguen existiendo. Tampoco impide DEL, expiraciones ni pérdida de almacenamiento. Sí hace visible el exceso de capacidad como un error que puedes manejar, en lugar de borrar datos de trabajo para admitir nuevos.

La solución habitual al conflicto entre una caché descartable y una cola importante es separar instancias, con presupuestos y políticas diferentes. Cambiar de base lógica con SELECT 1 no separa RAM, CPU, persistencia ni un FLUSHALL; además Redis Cluster solo usa la base lógica cero.

#Mantener el servidor fuera del acceso público

En el laboratorio publicamos solo 127.0.0.1. Entre contenedores de una aplicación, usa una red privada y el nombre de servicio, sin publicar el puerto del servidor hacia Internet. Si el cliente y Redis cruzan una red no confiable, configura TLS y verifica certificados; rediss:// indica una conexión TLS en el cliente, pero no activa TLS mágicamente en un servidor que no lo ofrece.

Una contraseña limita quién entra; una ACL limita además qué puede hacer después. No pongas la contraseña dentro del repositorio, una URL de log ni el código HTML de la aplicación. La aplicación de navegador no debe hablar directamente con Redis: su backend aplica autenticación y permisos.

#ACL: demostrar una autorización permitida y dos denegadas

Una ACL asocia un usuario a comandos y patrones de claves. Esta práctica añade un usuario restringido a nuestra instancia local. El usuario default permanece como administrador del laboratorio; no estamos afirmando que ese servidor quede listo para exponerlo a otra red.

import secrets
import redis

admin = redis.Redis(host="127.0.0.1", port=6380, decode_responses=True)
password = secrets.token_hex(24)
admin.execute_command(
    "ACL", "SETUSER", "aplicacion", "reset", "on", f">{password}",
    "~curso:permitido:*", "-@all", "+ping", "+get", "+set", "+ttl",
)
app = redis.Redis(host="127.0.0.1", port=6380, username="aplicacion",
                  password=password, decode_responses=True, protocol=2)
app.set("curso:permitido:saludo", "hola", ex=60)
print(app.get("curso:permitido:saludo"))
for comando in [("GET", "curso:privado:1"), ("FLUSHALL",)]:
    try:
        app.execute_command(*comando)
    except redis.exceptions.NoPermissionError:
        print("Denegado", comando[0])
app.close()
admin.execute_command("ACL", "DELUSER", "aplicacion")
admin.close()

reset limpia permisos anteriores para que repetir la práctica no acumule privilegios. on habilita el usuario. >contraseña añade una contraseña; el valor solo vive en la variable, no lo imprimimos. ~curso:permitido:* limita claves. -@all retira comandos y los + añaden exclusivamente los necesarios. El resultado esperado es hola y dos denegaciones.

El asterisco en *comando desempaqueta una tupla como argumentos: ("GET", "clave") se convierte en dos argumentos separados. No es código descargado ni una evaluación dinámica. execute_command envía esos argumentos mediante el protocolo del cliente.

#Llevar los permisos a una configuración durable

ACL SETUSER modifica el estado del servidor en ejecución. Un reinicio no conserva esa configuración automáticamente por tener AOF: los permisos no son claves de aplicación. Para operación, usa un archivo ACL gestionado, configura aclfile y verifica qué procedimiento persiste los cambios (ACL SAVE cuando hay archivo configurado).

Prepara primero una credencial administrativa y comprueba que permite gestionar usuarios desde una segunda conexión. Después desactiva el acceso anónimo de default conforme a tu configuración. No cierres tu único acceso sin verificar el alternativo. Limita el usuario de la aplicación y conserva administración en un canal separado. Comprueba de nuevo permisos después de reiniciar.

No concedas +@all para resolver un fallo puntual del cliente. Algunas bibliotecas envían comandos de identificación o salud; identifica el comando exacto mediante los errores o ACL LOG, y concede solo lo necesario. Las reglas de Pub/Sub usan también patrones de canal &..., distintos de patrones de claves.

#Aislamiento: decide qué riesgo intentas contener

Un prefijo evita que dos aplicaciones llamen igual a sus claves. Una ACL puede impedir que una lea las de otra, si los comandos concedidos y sus patrones lo permiten. Ninguna de esas medidas impide que una aplicación autorizada consuma todo el presupuesto compartido o ejecute un comando costoso entre los permitidos.

Para clientes de confianza diferente o cargas con picos incompatibles, separa procesos o instancias, limita recursos y usa red/credenciales propias. No presentes los números de base lógica como aislamiento multitenant. La autorización también debe comprobarse en el backend: si todas las peticiones usan el mismo usuario Redis con acceso a todos los prefijos, Redis no sabe qué usuario web pidió cada dato.

La referencia de políticas de expulsión documenta memoria y muestras aproximadas. La guía ACL detalla reglas y persistencia. La comprobación final es práctica: el cliente autorizado realiza su operación y falla al cruzar el límite previsto.

    ↑ ↓ para recorrer · Intro para abrir · Ctrl K para buscar