Presentación que relata las distintas técnicas para optimizar una aplicación web. El objetivo del documento consiste en introducir al participante en los conceptos sobre escalabilidad horizontal, instalar y trabajar con Redis como base de datos NoSQL In-Memory y aplicar un ejemplo de conectarnos con Redis desde una aplicación PHP.
6. Arquitectura web tradicional
Servidor web
IP: 200.151.2.90
Servidor
Base de Datos
IP: 200.151.2.201
Navegador webUsuario
TCPHTTP
Request
Response
Tiempos
en conectividad
y procesamiento
3
5
2
4
6
1
7
8
Front-End Back-End
12. CSS al inicio del Header
JS al final del Body
Consejos para optimizar - Front-End
13. Imágenes pesadas = sitio web lento
Optimice sus imágenes
Consejos para optimizar - Front-End
14. Consejos para optimizar - Back-End
Para optimizar el back-end hay que revisar la
arquitectura de nuestra aplicación
Servidor web
IP: 200.151.2.90
Apache Server
Servidor
Base de Datos
IP: 200.151.2.201
MySQL Server
Navegador webUsuario
TCPHTTP
Request
Response
15. Consejos para optimizar - Back-End
Servidor Base de Datos
MySQL Server
Servidor web
Apache Server + PHP
Correcta configuración del httpd.conf
Utilizar best practices del lenguaje de
programación (PHP).
Reutilización de código (POO).
Optimización de código.
Derivar cálculos matemáticos y/o
fechas a servidor de base de datos.
Enviar múltiples sentencias SQL en
pocas conexiones a la base de datos.
En una consulta SQL selecciona los
campos que necesites.
Utiliza índices para mejorar el tiempo
de respuesta de las consultas SQL.
Correcta configuración del my.conf
Utilizar MyISAM si tu prioridad son las
consultas SQL.
¡Para una aplicación tradicional estos consejos son válidos pero
las aplicaciones web han evolucionado!
17. Evolución de las aplicaciones web
Hace aproximadamente 20 años nacieron las
primeras aplicaciones web
ejecutadas en servidores de PC de
oficina.
Servidores PC de oficina
Estos servidores generaban
mucho calor y requerían
de un ventilador cada vez mayor.
18. Luego, las aplicaciones fueron aumentando de tamaño
y se necesitaban servidores más potentes y que ocupen
menos espacio.
Así surgió el servidor en forma de caja de pizza.
Servidores Blade
Estas se podrían apilar unas encima de otras.
19. La infraestructura se veía resuelta, pero a pesar de
tener con muchos servidores, había un problema.
Servidores apilados
Una aplicación solo se ejecutaba desde un servidor.
Servidor N° 1
Servidor N° 2
Servidor N° 3
App N° 1
App N° 2
App N° 3
20. Esto se convirtió en un gran problema, por que con
el continuo crecimiento de Internet,
estas aplicaciones se volvieron más populares.
Servidores apilados
Servidor N° 1
Servidor N° 2
Servidor N° 3
Servidor N° 4
Servidor N° 5
Servidor N° 6
App N° 1
App N° 2
App N° 3
App N° 4
App N° 5
App N° 6
21. Y más y más populares.
Servidores apilados
Servidor N° 1
Servidor N° 2
Servidor N° 3
Servidor N° 4
Servidor N° 5
Servidor N° 6
App N° 1
App N° 2
App N° 3
App N° 4
App N° 5
App N° 6
Y como hay un límite en la ejecución de un servidor.
Esta arquitectura no era sostenible y debía ser cambiada.
22. ¿Cuáles son las opciones para aumentar la capacidad
de nuestra aplicación web?
Opción N° 1: ¿Comprar un hardware más poderoso?
Opción N° 2: ¿Optimizar el software?
Opción N° 3: ¿Copiar y ejecutar el software en más servidores?
Opción N° 4: ¿Cambiar el software para ejecutarlo en
más servidores?
23. ¿Cuáles son las opciones para aumentar la capacidad
de nuestra aplicación web?
Al cambiar el software para que se ejecute en
más servidores, comienzas a trabajar con una
arquitectura escalable. Con esto haces que la
capacidad no se limite por el hardware que
utilices o por cuanto optimices tu aplicación.
Cuando necesites crecer, puedes agregar más
servidores.
Opción N° 1: ¿Comprar un hardware más poderoso?.
Opción N° 2: ¿Optimizar el software?
Opción N° 3: ¿Copiar y ejecutar el software en más servidores?
Opción N° 4: ¿Cambiar el software para ejecutarlo en
más servidores?
24. Desasociar la ejecución
Servidores apilados
Servidor N° 1
Servidor N° 2
Servidor N° 3
Servidor N° 4
Servidor N° 5
Servidor N° N
Desasociar la ejecución de una aplicación convierte a nuestro
diseño en una arquitectura escalable scale-out o también
llamada escalabilidad horizontal.
25. ¿Cuándo una aplicación web es
escalable?
Para que un sistema sea escalable, tiene que
cumplir 3 condiciones:
34. Arquitectura Share Nothing
Para que nuestra aplicación web
pueda escalar horizontalmente,
suele utilizarse una arquitectura
“Share Nothing”, es decir que cada
nodo de la aplicación son:
Independientes
Auto contenidos
Autosuficientes
Importante: Estado de la aplicación es compartida por todo el Sistema
35. Mitos sobre la escalabilidad
2. La escalabilidad no es lo
mismo que el rendimiento
del sistema.
1. La escalabilidad depende del diseño de la
arquitectura, no de la tecnología utilizada.
36. Con un Internet que crece
rápidamente, la optimización
de una aplicación web
se enfoca en atender
la alta demanda del
objetivo estratégico de
muchas organizaciones
digitales, como es el…
USER
EXPERIENCE
37. User Experience en una aplicación web
Dependiendo del objetivo
de nuestra aplicación
web, es importante
ofrecerle al usuario:
Velocidad
Usabilidad
Utilidad
Disponibilidad 24x7
Seguridad
39. Motor avanzado de base de datos key-value
Servidor de Base de datos NoSQL de alta velocidad.
Servidor de estructuras de datos escalable.
¿Es mejor cambiar nuestras base de datos relacionales
a una base de datos NoSQL?
REmote Dictionary Server
40. Salvattore Sanfilippo @antirez
Apareció en Diciembre 2009
Escrito en ANSI C, open source, licencia Free BSD
Soporte oficial en plataformas UNIX.
Diseñado para escalar horizontalmente.
Se ejecuta en un solo proceso de forma asíncrona.
Transacciones atómicas.
Conexión TCP / Port Listen 6379
LUA Scripting
Redis Cluster
Memoria RAM
Página Oficial: http://redis.io
41. “Memory is the new disk.
Disk is the new Tape”
Jim Gray
Recibió premio Turing en 1998 por
sus contribuciones originales a la
investigación de base de datos y
procesamiento de transacciones.
42. 1. Snapshotting:
La data es transferida asíncronamente desde la
memoria al disco duro.1. Ff
Persistencia en Redis
Arquitectura Master-Slave por replicación.
Persistencia en disco vía snapshots.
10,000 conexiones concurrentes por default.
43. 2. Append Only File (AOF):
• Cada operación de modificación en las estructuras
de datos de Redis es escrito a un archivo.
• Ventaja: Disponibilidad de cambios en los datos
ante una caída de Redis.
• Desventaja: La performance baja al escribir
constantemente al disco.
IMPORTANTE:
Si Redis necesita reiniciar, le tomará entre 10 a 20 segundos
aproximadamente volver a cargar 1 GB de data en memoria RAM.
1. Ff
Persistencia en Redis
47. Proyectos de analítica en tiempo real.
Almacenar colas de tareas.
Memoria compartida por aplicaciones,
servidores, procesos.
Apps con alta demanda I/O.
Contadores.
Notificaciones en tiempo real.
¿Cuándo usar Redis?
49. Instalando
Apache/MySQL/PHP/Redis
Para el presente taller trabajaremos sobre la distribución Linux CentOS.
1. Instalando herramienta wget
$> yum -y install wget
2. Instalando MySQL-Server
$> yum -y install mysql mysql-server
3. Instalando Apache Server
$> yum -y install httpd
4. Instalando PHP y modulos.
$> yum -y install php
$> yum -y install php-mysql php-devel php-xml php-mbstring php-mcrypt php-soap
5. Descargando RPM e instalando redis.
$> wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
$> rpm -Uvh epel-release*rpm
$> yum -y install redis
50. Instalando PHPRedis
PHPRedis es una extensión que proporciona una API para comunicarnos con Redis
desde PHP.
1. Instalando herramienta git
$> yum -y install git
2. Descargando phpredis
$> git clone https://github.com/gchacaltana/phpredis.git
3. Instalando PHPRedis
$> cd phpredis
$> phpize
$> ./configure
$> make
$> make test
$> make install
$> echo 'extension=redis.so' | tee --append /etc/php.ini
$> touch /var/www/html/info.php
$> echo '<?php phpinfo(); ?> ' | tee --append /var/www/html/info.php
51. Levantando servicios
1. Iniciando servicio de Apache Server
$> service httpd start
2. Iniciando servicio de MySQL Server
$> service mysqld start
3. Iniciando servicio de Redis Server
$> service redis start
53. Keys en Redis
Creando un string key-value
redis > SET nombre “Gonzalo”
redis > SET apellido “Chacaltana”
Obteniendo valor de string
redis > GET nombre
“Gonzalo”
redis > GET apellido
“Chacaltana”
El valor de un string puede tener como máximo 512 MB.
54. Keys en Redis
Creando un string key-value con ORDEN
Esquema:
proyecto:entidad:instancia:atributo
Ejemplo:
redis > SET intranet:alumno:20150201:nombre “Luisa”
redis > SET intranet:alumno:20150201:apellidos “Loo Sang”
redis > GET intranet:alumno:20150201:nombre
“Luisa”
redis > GET intranet:alumno:20150201:apellidos
“Loo Sang”
55. Keys en Redis
Trabajar con una base de datos NoSQL nos obliga a
pensar menos en modelos relacionales y más en
estructuras key : value
56. Validar existencia de Key (string)
redis > EXITS sys:cliente:name
0
Concatenar string
redis > SET sys:cliente:name “Mario”
redis > APPEND sys:cliente:name “ Fernando”
redis > GET sys:cliente:name
“Mario Fernando”
Keys en Redis
57. Visualizar todos los Keys (Llaves)
redis > KEYS *
redis > KEYS intranet:alumno:*
Tener precaución de usarlo en producción.
Eliminar un Key
redis > DEL key
Eliminar todos los Key por patrón de coincidencia
desde consola Linux.
$ > redis-cli KEYS “session:*” | xargs –n 10 redis-cli DEL
Keys en Redis
58. Cantidad de Keys (Llaves)
redis > DBSIZE
Cantidad de Keys desde la consola de linux
$ > redis-cli KEYS "*" | wc –l
Expirar un Key
redis > SET user:pepito “loged”
redis > EXPIRE user:pepito 25
Visualizar tiempo de expiración
redis > TTL user:pepito
Keys en Redis
59. Quitar tiempo de expiración
redis > SET user:jaimito “loged”
redis > EXPIRE user:jaimito 50
redis > TTL user:jaimito
redis > PERSIST user:jaimito
redis > GET user:jaimito
Obtener múltiples KEY (string)
redis > SET factura:001543:cliente “Cemento Lima S.A.C”
redis > SET factura:001543:fecha “11/07/2015”
redis > SET factura:001543:importe “25500.50”
redis > MGET factura:001543:cliente factura:001543:fecha
factura:001543:importe
Keys en Redis
60. Insertar múltiples KEYs
redis > MSET auto:marca “Toyota” auto:modelo “Corola”
Incrementar/Disminuir valor de KEY (número)
redis > SET contador:usuarios “0”
redis > INCR contador:usuarios
1
redis > INCR contador:usuarios
2
redis > GET contador:usuarios
2
redis > DECR contador:usuarios
1
Keys en Redis
61. Incrementar/Disminuir valor de KEY (número) con valor
fijo.
redis > SET jugadores:vivos “5”
redis > INCRBY jugadores:vivos 4
9
redis > INCRBY jugadores:vivos 2
11
redis > DECRBY jugadores:vivos 6
5
redis > GET jugadores:vivos
5
Obtener valor e inicializar KEY (contador numérico)
redis > GETSET jugadores:vivos
5
Keys en Redis
63. Implementando una cola de tareas
redis > LPUSH queue:efact “E001245”
redis > LPUSH queue:efact “E001244”
redis > LRANGE queue:efact 0 -1
“E001244”
“E001245”
redis > RPUSH queue:efact “E001246”
redis > LRANGE queue:efact 0 -1
“E001244”
“E001245”
“E001246”
Sintaxis: LRANGE KEY start stop
List en Redis
64. Obteniendo y eliminando automáticamente de la cola al
primer elemento. No devolverá hasta que halla un
elemento que devolver. (version bloqueante del LPOP)
Consola 1
redis > BLPOP queue:efact 0
“E001244”
Consola 2
redis > LRANGE queue:efact 0 -1
“E001245”
“E001246
List en Redis
La longitud máxima de una lista es de 4 Billones de elementos.
65. Eliminar/contar elementos de una lista.
redis > RPUSH lista:alumnos “Ana”
redis > RPUSH lista:alumnos “Camila”
redis > RPUSH lista:alumnos “David”
redis > RPUSH lista:alumnos “Ana”
redis > RPUSH lista:alumnos “Fernando”
redis > LLEN lista:alumnos
5
redis > LREM lista:alumnos -1 “Ana”
Sintaxis: LREM lista count value
• count > 0: Elimina “count” elementos del HEAD a TAIL.
• count < 0: Elimina “count” elementos del TAIL a HEAD.
• count = 0: Elimina todos los elementos igual al valor.
List en Redis
66. Un Set en Redis es un conjunto desordenado de
strings. Tienen la propiedad de no repetir sus
elementos.
redis > SADD productos “Televisor LG”
redis > SADD productos “Refrigeradora Coldex”
redis > SADD productos “Licuadora Oster”
redis > SADD productos “Televisor LG”
0
redis > SMEMBERS productos
“Televisor LG”
“Refrigedora Coldex”
“Licuadora LG”
redis > SCARD productos
Set en Redis
67. Validación de existencia de miembro de conjunto (Set).
redis > SADD facturas “F001-005421”
redis > SISMEMBER facturas “F002-9999”
0
redis > SISMEMBER facturas “F001-005421”
1
Cantidad de elementos de una lista.
redis > SCARD productos
Set en Redis
69. Similares a los Set, a diferencia que cada
miembro tiene asignado un score para ser
ordenado.
redis > ZADD user:followers 250 barackobama
redis > ZADD user:followers 85 ollantahumala
redis > ZADD user:followers 185 paologuerrero
redis > ZINCRBY user:followers 4580 barackobama
redis > ZINCRBY user:followers 398 ollantahumala
redis > ZINCRBY user:followers 3890 paologuerrero
redis > ZRANGE user:followers 0 -1 WITHSCORES
redis > ZRANK user:followers barackobama
redis > ZREVRANGE users:followers 0 -1 WITHSCORES
redis > ZRANGEBYSCORE users:followers –inf 4000
redis > ZRANGEBYSCORE users:followers 3000 5000
Sorted Set en Redis
70. Son estructuras de datos key-value que
se asemejan más al almacenamiento de
objetos.
redis > HMSET twitter:user:1354 username
“@paolo_guerrero_” name “Paolo Guerrero”
joindate “2008-07-12”
redis > HGETALL twitter:user:1354
redis > HGET twitter:user:1354 name
redis > HEXISTS twitter:user:1354 surname
redis > HEXISTS twitter:user:1354 surname
redis > HKEYS twitter:user:1354
redis > HLEN twitter:user:1354
redis > HMGET twitter:user:1354 name joindate
redis > HVALS twitter:user:1354
Hashes en Redis
71. Eliminando campos de Hash
redis > HSET twitter:user:1354 fecha “12/02/1988”
redis > HDEL twitter:user:1354 fecha
Contadores en campos de Hash
redis > HINCRBY twitter:user:1354 following 8
redis > HINCRBY twitter:user:1354 following -62
redis > HVALS twitter:user:1354
Hashes en Redis
74. Creando una librería
Creamos una librería donde centralizar todos los métodos
para acceder al servidor de redis.
Class RedisLibrary
{
private $server;
private $port;
public function __construct($server = NULL, $port = NULL)
{
$this->server = (isset($server)) ? $server : "127.0.0.1";
$this->port = (isset($server)) ? $server : "6379";
}
}
75. Creando una librería
Dentro de nuestra librería, creamos los métodos.
private function connect()
{
try {
if (!class_exists('Redis')) {
throw new Exception("Redis extension not found.");
}
$connection = new Redis();
$connection->connect($this->server, $this->port);
} catch (Exception $e) {
throw new Exception("There was a problem connecting to redis server.");
}
//validate redis connection
if (isset($connection->socket)) {
return $connection;
} else {
throw new Exception("The redis server is turned off.");
}
}
76. Creando una librería
Dentro de nuestra librería, creamos los métodos.
public function setSortedSet($set, $key, $value)
{
$redis = $this->connect();
//El metodo zAdd agrega un elemento a una lista ordenada de Redis
$redis->zadd($set, $key, $value);
//cerramos la conexion a Redis.
$redis->close();
return true;
}
public function zIncrBy($set, $value, $member)
{
$redis = $this->connect();
//El metodo zIncrBy incrementa score de un elemento del sorted set
$redis->zIncrBy($set, $value, $member);
//cerramos la conexion a Redis.
$redis->close();
return true;
}
77. Creando script cliente
require_once 'RedisLibrary.php';
$obj = new RedisLibrary();
$users = array("Marlon", "Fresita", "Angelito", "Winner", "Zylex", "Gatito");
$number_games = 100;
for ($game = 1; $game <= $number_games; $game++) {
$key = mt_rand(0, count($users) - 1);
$score = mt_rand(0, 10);
if ($obj->zIncrBy("players:score", $score, $users[$key])) {
echo sprintf("%s ganó %d punto(s) en la partida %d<br/>",
$users[$key], $score, $game);
}
}
78. Conclusiones
1. Redis es una poderosa herramienta para almacenar
grandes cantidades de datos en tiempo real.
2. Redis ofrece un rápido servicio de lectura y escritura
concurrente.
3. Podemos realizar monitoreo y detección de eventos
de nuestra colección de datos almacenamos en Redis.
4. Redis nos ofrece estabilidad funcional, escalabilidad,
un sistema de notificaciones real-time usando un
canal publish/suscriber
79. Referencias
Building Scalable
Web Sites
Cal Henderson
Redis Cookbook
Tiago Macedo
Fred Oliveira
Scaling PHP Applications
Steve Corona
Seven Databases
in Seven Weeks
Eric Redmond
Jim R. Wilson