Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Optimización de aplicaciones web con base de datos NoSQL In-Memory

Optimización de aplicaciones web con base de datos NoSQL In-Memory

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.

Gonzalo Chacaltana

July 11, 2015
Tweet

More Decks by Gonzalo Chacaltana

Other Decks in Programming

Transcript

  1. Optimización de aplicaciones web con Base de Datos NoSQL In-Memory

    Ing. Gonzalo Chacaltana gchacaltanab Julio 2015
  2. La pregunta ahora es… ¿Por qué debemos …. ¿Cuándo debemos…

    ¿Cómo puedo… ¿Quién debe… optimizar una aplicación web?
  3. Arquitectura web tradicional Servidor web IP: 200.151.2.90 Servidor Base de

    Datos IP: 200.151.2.201 Navegador web Usuario TCP HTTP Request Response Tiempos en conectividad y procesamiento 3 5 2 4 6 1 7 8 Front-End Back-End
  4. CSS al inicio del Header JS al final del Body

    Consejos para optimizar - Front-End
  5. 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 web Usuario TCP HTTP Request Response
  6. 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!
  7. 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.
  8. 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.
  9. 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
  10. 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
  11. 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.
  12. ¿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?
  13. ¿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?
  14. 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.
  15. ¿Cuándo una aplicación web es escalable? Para que un sistema

    sea escalable, tiene que cumplir 3 condiciones:
  16. Condición N° 2 : Tiene que poder adaptarse a un

    incremento en el tamaño de datos que maneja.
  17. 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
  18. 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.
  19. 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
  20. 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
  21. 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
  22.  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
  23. “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.
  24. 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.
  25. 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
  26.  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?
  27. 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
  28. 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
  29. 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
  30. Conociendo Redis Servidor > redis-server Cliente > redis-cli Ingresando al

    cliente de redis. $> redis-cli Información de Redis. $> info
  31. 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.
  32. 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”
  33. 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
  34. 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
  35. 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
  36. 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
  37. 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
  38. 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
  39. 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
  40. 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
  41. 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.
  42. 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
  43. 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
  44. 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
  45. Operaciones entre conjuntos. redis > SADD simcard:stock "996545212" redis >

    SADD simcard:stock "987542155" redis > SADD simcard:stock "987454454" redis > SADD simcard:stock "954544545“ redis > SADD simcard:vendidos "987454454" redis > SADD simcard:vendidos "987542155“ redis > SADD simcard:vendidos "978451500“ redis > SINTER simcard:stock simcard:vendidos “987454454” “987542155” redis > SDIFF simcard:stock simcard:vendidos “996545212” “954544545” Set en Redis
  46. 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
  47. 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
  48. 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
  49. 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"; } }
  50. 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."); } }
  51. 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; }
  52. 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); } }
  53. 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
  54. 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
  55. Optimización de aplicaciones web con Base de Datos NoSQL In-Memory

    Gracias ¿PREGUNTAS? Ing. Gonzalo Chacaltana gchacaltanab Julio 2015