Compresión GZIP y Redis

En mi antiguo trabajo hacíamos muchas peticiones a proveedores externos. De media eran unas 2K peticiones por segundo. Unos 170M peticiones al día. Cada una de éstas peticiones tenía su correspondiente respuesta, que acostumbraba a ser un JSON, pero podía ser un XML. El peso dependía mucho de la respuesta, pero variaba entre pocos KB hasta casi 1MB.

Guardábamos la respuesta en Redis, durante un breve periodo de tiempo (segundos). Al principio, guardábamos los datos «tal cual» y, obviamente, era un error.

GZIP

Comprimir texto es asquerosamente rápido. Hay muchos algoritmos de compresión, pero normalmente conseguiremos un 80% de compresión con respecto al tamaño original, y podemos comprimir entre 15 hasta 60MB/segundo.

En nuestro caso, no sólo era el tamaño en RAM que ocupaba éstos datos en el cluster de Redis, sino la transferencia de datos para guardar las claves en Redis, y leerlas seguidamente. Simplemente guardando información comprimida reducíamos dicho tráfico al 10-20% del original.

Demostración

En este caso usaremos Python para hacer la pequeña prueba:

import redis
import gzip

client = redis.Redis()

payload = "abcdef" * 100_000  # 600K string

client.set("no-compressed", payload)
print("non-compressed length:", client.strlen("no-compressed"))


payload_compressed = gzip.compress(bytes(payload, 'utf-8'))
client.set("compressed", payload_compressed)
print("compressed length:", client.strlen("compressed"))

payload_compressed_retrieved = client.get("compressed")
print("Compressed payloads are equal:", payload_compressed == payload_compressed_retrieved)
print("Uncompressed payload length:", len(gzip.decompress(payload_compressed_retrieved)))

si ejecutamos el script veremos el siguiente resultado:

non-compressed length: 600000
compressed length: 913
Compressed payloads are equal: True
Uncompressed payload length: 600000

En Redis pasamos a tener una clave de 600K a 0.9K. Es una mejora de 600x. Obviamente esto no es un caso real, puesto que el payload original lo repetimos 100.000 veces y justamente GZIP es especialmente eficiente en comprimir éstos tipos de datos.

En un caso bueno donde comprimas texto, quedarte con un 10% del original ya está muy bien, y le sacaremos gran provecho.

Redis

A Redis realmente le da igual lo que almacenemos como string.

Strings are the most basic kind of Redis value. Redis Strings are binary safe, this means that a Redis string can contain any kind of data, for instance a JPEG image or a serialized Ruby object.

https://redis.io/topics/data-types

Simplemente estamos usando el hecho de que podamos tipos de datos binarios, y Redis nos va a devolver tal cual lo que le hayamos guardado originalmente esté o no comprimido.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *