2. ¿Quién soy?
Ronny López @ronnylt
Desarrollador @pricebets
Descubrí Redis cuando una consulta como esta hacia que una
página demorara +15 segundos en cargar:
SELECT value
FROM odds
INNER JOIN outcomes ON ...
INNER JOIN bets ON ...
INNER JOIN markets ON ...
...
WHERE ... ORDER BY ...
4. Pero...
• Hay tareas que no necesitan tanta complejidad
• El modelo relacional actual es difícil de escalar
horizontalmente
• No se pueden modelar problemas comunes lo
suficientemente bien
5. ¿Qué es Redis?
• Remote dictionary server
• Motor de almacenamiento clave-valor avanzado,
rápido y persistente
• Servidor de estructuras de datos
• NoSQL (Not-only SQL)
• Open source
6. ¿Quién está detrás de
Redis?
• Creado por Salvatore Sanfilippo @antirez
• Release inicial en marzo del 2009
• Actualmente el desarrollo es patrocinado por
VMWare
• Comunidad activa y amigable
7. ¿Quién usa Redis?
• Usado hoy en el mundo real por grandes y
pequeñas empresas
• Resolviendo grandes y pequeños problemas
9. ¿Para qué lo usan?
• github.com: motor de almacenamiento clave/valor, cola de trabajos
(resque)
• guardian.co.uk: servidor de estructuras de datos persistente
• disqus.com: sistema estádistico desarrollado sobre Redis
• stackoverflow.com: capa de cache para toda su red
• flickr.com: lista de trabajos
• pricebets.es: almacenamiento primario (conjuntos, listas, hashes, etc...),
routing, cache, sessions
10. Características
principales
• Escrito en C
• Muy pocas dependencias
• Super rápido
• Single-threaded
• Clientes disponibles para varios lenguajes
11. Características
principales
• Alto rendimiento en escritura y lectura
• Soporte de operaciones atómicas
• Soporte de transacciones
12. Características
Simplicidad
• Fácil instalación
• Curva de aprendizaje relativamente baja
• Lenguage de comandos fácil de utilizar y aprender
13. Características
Previsibilidad
• La memoria es rápida, y permite a Redis tener un
redimiento muy fiable
• Operaciones sobre datasets de 10 mil claves tendrán
el mismo rendimiento que sobre datasets de 50
millones de claves
• La complejidad algorítmica de todos los comandos
está documentada
14. Características
Confiabilidad
• Todos los datos residen en memoria, y son persistidos
a disco eventualmente (snapshots, append-only log)
• Replication system (master-slave) , pueden configurarse
múltiples esclavos. Un esclavo puede ser el master de
otro esclavo
15. Características
Persistencia
• RDB, Point-in-time snapshots en intervalos
configurados
• AOF (append-only file) cada operación de
escritura
• Es posible combinar RDB y AOF en la misma
instancia
• Se puede deshabilitar la persistencia del todo
16. Características
Versatilidad
• Adaptable a varios tipos de aplicaciones
• Modelado de los datos a partir de estructuras de
datos como listas, conjuntos, conjuntos ordenados
y hashes
17. Tipos de datos
• Redis NO es simplemente un motor de
almacenamiento clave-valor
• Es un servidor de estructuras de datos que incluye
varios tipos de datos predefinidos (strings, lists,
sets, sorted sets, hashes)
18. Claves
• Puede usarse cualquier cadena de caracteres como
clave
• Es recomendable tener organizadas las claves en
namespaces (keyspaces) de la forma:
object-type:id:field
Ejemplo:
user:123:password
user:456:friends
19. Claves
• NO es recomendable que las claves sean demasiado
grandes (memoria, localización en el keyspace)
• Tampoco es recomendable que las claves sean
demasiado cortas por cuestiones de legibilidad
Ejemplo: u:123:pw
20. Tipos de datos
Strings
• Es el tipo de dato más simple
• Si solamente usa este tipo de dato es similar a usar
un servidor memcached pero con persistencia
21. Operaciones con
Strings
$ redis-cli SET mykey “binary-safe string”
OK
$redis-cli GET mykey
binary-safe string
22. Operaciones
Strings
• Comandos SET/GET para escribir/leer
• Los valores pueden ser cualquier string no mayor
que 1 GB
• Si necesita almacenar algo más grande, Redis is NOT
for you ;)
24. ¿Por qué atómico?
Aún cuando hayan varios clientes ejecuntando
operaciones sobre la misma clave, no se va a incurrir
en una condición de carrera (race condition)
26. Tipos de datos
Lists
• Son simplemente una secuencia de elementos
(strings) ordenados
• Son implementadas como listas enlazadas
27. Tipos de datos
Lists
• Listas doblemente enlazadas garantizan la inserción
en cualquier extremo en un tiempo constante
O(1)
• Con estas caterísticas también puede modelarse
una “cola”
28. Operaciones
Lists
• LPUSH agrega un elemento en el extremo
izquierdo de la lista
• RPUSH en el extremo derecho
• LRANGE extrae elementos de la lista en cierto
rango
30. Variantes “blocking”
• BLPOP, BRPOP, BRPOPLPUSH
• Bloquean la conexión (del cliente) cuando no hay
elementos en la lista
• Ideal para implementar colas de trabajos/mensajes
31. Operaciones
Lists
$ redis-cli RPUSH messages "Hola, ¿qué
tal?"
OK
$ redis-cli RPUSH messages "Bien, gracias"
OK
$ redis-cli RPUSH messages "Muy grande Redis"
OK
$ redis-cli LRANGE messages 0 2
1. Hola, ¿qué tal?
2. Bien, gracias
3. Muy grande Redis
32. Usos de las listas
• Utilice listas cada vez que requiera acceder a los
datos en el mismo orden en que se agregan
• Ideal para casos en los que se requiere un ORDER
BY de SQL
• Escalable a millones de elementos manteniendo el
mismo rendimiento
33. Ejemplos de uso de las
listas
• Mantener un listado cronológico de los comentarios
publicados en un blog
• Es posible paginar usando LRANGE de forma trivial
$ redis-cli RPOP post:123:comments 456
$ redis-cli RPOP post:123:comments 789
$ redis-cli LRANGE post:123:comments 50 60
34. Tipos de datos
Sets
• Colección NO–ordenada de datos (conjuntos)
• Permite operaciones típicas sobre conjuntos como
unión, intersección, diferencia, etc...
• Estas operaciones son difíciles de implementar en
un modelo relacional
38. Tipos de datos
Sorted Sets
• Un conjunto ordenado es un conjunto donde a
cada elemento se le asocia una puntuación (score)
• Este valor (score) determina el orden de los
elementos dentro del conjunto
39. Tipos de datos
Sorted Sets
• ZADD es usado para agregar nuevos elementos o para
actualizar el score de uno ya existente
$ redis-cli ZADD top-sites: 4 “pricebets”
(integer) 1
$ redis-cli ZADD top-sites: 6 “betabeers”
(integer) 1
$ redis-cli ZRANGE top-sites 0 -1
1. betabeers
2. pricebets
41. Tipos de datos
Hashes
• Permiten que objetos compuestos se almacenen en una
clave específica
• Tipo de dato ideal para almacenar objetos complejos
en Redis, usando los atributos del objeto como claves
del hash
42. Operaciones
Hashes
$ redis-cli HSET event:1 name betabeers
$ redis-cli HSET event:1 date 2012-01-17
$ redis-cli HSET event:1 where Barcelona
$ redis-cli HGETALL event:1
1) name
2) betabeers
3) date
4) 2012-01-17
5) where
6) Barcelona
45. Contadores
• Gran cantidad de escrituras/lecturas
• Datos valiosos, pero NO críticos
• Insertar una fila en MySQL o actualizar un
contador en cada petición será sin dudas difícil de
escalar
47. Casos de uso
Presencia
¿Quién está online?
¿Cuáles de mis amigos están online?
48. Presencia
• Mantener en un conjunto los usuarios que se
han detectado online en cada minuto
$ redis-cli SADD online:15:01 123
$ redis-cli SADD online:15:01 456
$ redis-cli SADD online:15:02 123
49. Presencia
• El conjunto de usuarios online se puede
obtener de la UNION de los conjuntos
relativos a los últimos ¿5? minutos.
A las 15:05
$ redis-cli SUNION online:15:01
online:15:02 online:15:03 online:
15:04 online:15:05
50. Presencia
• El conjunto de “amigos” online es otra
operación sobre conjuntos
$ redis-cli SUNION online:15:01
online:15:02 online:15:03 online:
15:04 online:15:05 user:123:friends
• Puede almacenarse en otra clave:
$ redis-cli SUNIONSTORE
friends:online:123 online:15:01
online:15:02 online:15:03 online:
15:04 online:15:05 user:123:friends
52. Tabla de posiciones
• Se necesita listar elementos ordenados por una
puntuación
• Las puntuaciones se actualizan en tiempo real
• Consultas lentas por naturaleza
SELECT * FROM ... WHERE ... ORDER BY ... LIMIT 10
53. Tabla de posiciones
• Mantener un conjunto ordenado (sorted set) con los
elementos y su score
$ redis-cli ZADD popular:sports 10 football
$ redis-cli ZADD popular:sports 6 basketball
$ redis-cli ZADD popular:sports 12 football
$ redis-cli ZREVRANGE popular:sports 0 9
55. URL Routing
• Convertir alias de URL a paths internos de la
aplicación
Ejemplo:
http://www.apuestas.com/futbol
=> /sport/1
http://www.apuestas.com/futbol/espana/copa-del-rey
=> /competition/3120
57. URL Routing
• Mantener un hash con el routing y otro con los alias
$ redis-cli HSET routing /futbol /sport/1
$ redis-cli HSET alias /sport/1 /futbol
• Tiempo constante O(1) para cualquier número de
rutas/alias
59. ¿Qué se espera para
próximas vesiones?
• Scripting (con LUA) (Redis 2.6)
• High resolution expires (Redis 2.6)
• Mejoras en el rendimiento de la escritura/lectura
de grandes objetos (Redis 2.6)
• Redis Cluster (Redis 3.0)
60. Algunos consejos
• Instancias de Redis en 64 bits consumen más RAM
• No usar el comando KEYS en producción
• Comando MONITOR para observar y monitorear
61. Benchmarks
Processor 2.2 GHz Intel Core i7
redis-benchmark -q -n 100000 Memory 8 GB 1333 MHz DDR3
PING (inline): 108459.87 requests per second
PING: 89766.61 requests per second
MSET (10 keys): 48053.82 requests per second
SET: 80064.05 requests per second
GET: 87108.02 requests per second
INCR: 82644.62 requests per second
LPUSH: 82169.27 requests per second
LPOP: 78802.20 requests per second
SADD: 71890.73 requests per second
SPOP: 93283.58 requests per second
LPUSH (again, in order to bench LRANGE): 86880.97 requests per second
LRANGE (first 100 elements): 64061.50 requests per second
LRANGE (first 300 elements): 40064.10 requests per second
LRANGE (first 450 elements): 30478.51 requests per second
LRANGE (first 600 elements): 25873.22 requests per second