Como parte del despliegue de OpenStack que estamos haciendo hace ya unos meses en el trabajo surgió la necesidad de contar con alta disponibilidad en el servicio de cache provisto por memcached (
Memcached es una sencilla pero muy poderosa solución de cache en memoria, utilizada por grandes personajes de Internet como Wikipedia, Youtube, Twitter, etc). En OpenStack, memcached se utiliza principalmente para proveer agilidad a la interfaz web Horizon.
Los siguientes 6 pasos deben ser aplicados a ambos servidores (cabe aclarar que este método solo permite 2 servidores, es una restricción del propio repcached).
1-Preparar el entorno
Debemos instalar una serie de paquetes para poder compilar nuestra propia versión de memcached con replicación.
root@memcached1:~/# apt-get build-dep memcached
2-Obtener el código de fuente
La forma mas sencilla de obtener el código de fuente es:
root@memcached1:~/# apt-get source memcached
3. Obteniendo el código de repcached
Repcached es un parche que aplicamos sobre el código de memcached, que nos da la capacidad de poder replicar nuestra cache en 2 servidores. Obtener el código de
https://github.com/usecide/repcached/blob/master/repcached-2.3.1-1.4.13.patch
root@memcached2:~# wget https://raw.github.com/usecide/repcached/master/repcached-2.3.1-1.4.13.patch
4-Aplicar el parche
root@memcached1:~/# mv repcached-2.3.1-1.4.13.patch memcached-1.4.13/
root@memcached1:~/# cd memcached-1.4.13/
root@memcached1:~/memcached-1.4.13# patch -p1 -i repcached-2.3.1-1.4.13.patch
5-Configurar, Compilar e Instalar
root@memcached1:~/memcached-1.4.13# ./configure –enable-replication
root@memcached1:~/memcached-1.4.13# make
root@memcached1:~/memcached-1.4.13# make install
"make install", si todo sale bien nos dejará nuestra versión de memcached en el directorio /usr/local/bin/.
6-Puesta en marcha
Necesitamos una serie de retoques para poner a punto nuestro memcached con replicación.
Primero debemos crear un script de arranque que nos permite iniciar/reiniciar/detener el servicio a gusto y placer y ubicarlo en /etc/init.d/ con el nombre memcachedrep, el archivo se puede obtener de
http://pastebin.com/WfxPV81W ; luego es necesario hacer el archivo ejecutable:
root@memcached1:~/memcached-1.4.13# chmod +x /etc/init.d/memcachedrep
Como segundo paso creamos un archivo de configuración para el servicio en /etc/default/ con nombre memcachedrep y escribimos la siguiente linea en él:
DAEMON_ARGS="-m 256 -p 11211 -u root -P /var/run/memcachedrep.pid -d -v -t 4 -x 172.16.254.118"
Siendo:
-m 256: utilizar 256Mb de memoria para almacen.
-p 11211: escucha peticiones en el puerto 11211, TCP y UDP
-u root: usuario con el que ejecutará el demonio
-P /var/run/memcachedrep.pid: archivo que contendrá el PID del demonio en ejecución
-d: lanza memcached en modo demonio
-v: modo verborrágico, nos permitirá ver advertencias y errores en la ejecución
-t 4: cantidad de hilos que utilizará memcached
-x 172.16.254.118: este parámetro es propio del parche repcached e indica quien es el servidor con el que se replicará. En nuestro caso los servidores son 172.16.254.117 (memcached1) y 172.16.254.118 (memcached2). Por defecto los servidores se sincronizaran utilizando una conexión dedicada en el puerto 11212.
Por último agregamos memcachedrep a los servicios del sistema:
root@memcached1:~/memcached-1.4.13# update-rc.d memcachedrep defaults
7-Probando la replicación
Bien, ahora llega la parte divertida, ya tenemos ambos servidores listos para correr nuestra versión de memcached con replicación.
Iniciamos memcachedrep en el nodo memcached1:
root@memcached1:~# service memcachedrep start
root@memcached1:~# replication: connect (peer=172.16.254.118:11212)
replication: marugoto copying
replication: close
replication: listen
root@memcached1:~#
podemos ver que la replicación se encuentra "close", esto se debe a que la instancia de memcached que lanzamos no pudo conectarse con el otro nodo (172.16.254.118 memcached2). Podriamos utilizar solamente este nodo, en caso de que el otro no funcione.
Ahora iniciamos el segundo nodo:
root@memcached2:~# replication: connect (peer=172.16.254.117:11212)
replication: marugoto copying
replication: start
root@memcached2:~#
Perfecto, ambas instancias están levantadas y conectadas. Podemos verificar que se han conectado con el siguiente comando:
root@memcached2:~# netstat -ntap|grep ESTA|grep 11212
tcp 0 0 172.16.254.118:35734 172.16.254.117:11212 ESTABLISHED 31503/memcached
root@memcached2:~#
También podemos ver en el nodo memcached1 un mensaje indicandolo:
root@memcached1:~# replication: accept
Ahora viene la prueba de fuego, cargamos un dato en el nodo memcached1 y lo buscamos en memcached2:
root@memcached1:~# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
set juan 0 0 4
jose
STORED
quit
Connection closed by foreign host.
root@memcached1:~#
root@memcached2:~# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
get juan
VALUE juan 0 4
jose
END
quit
Connection closed by foreign host.
root@memcached2:~#
Y así podemos apreciar el efecto de la replicación. Si sumada a la replicación, ubicamos delante de ambos servidores un balanceador TCP como haproxy logramos sencillamente un mecanismo de cache con alta disponibilidad y balanceo de carga.
Lamentablemente el proyecto repcached se encuentra en un estado no muy activo y por lo tanto dificilmente haya novedades al respecto, pero sin lugar a dudas es una buena opción para lograr estos objetivos.