Buscando mecanismos para incrementar la disponibilidad y escalabilidad de mis servidores MySQL, decidí hacer pruebas con MySQL Cluster, una excelente solución para dichas necesidades.
Este documento pretende explicar su puesta en marcha sobre FreeBSD, una plataforma no soportada por Oracle y en la cual tendrémos que realizar algunos trucos para que funcione correctamente.
Introducción
Por el momento, el documento se enfoca en la implementación mas que en los conceptos y definiciones de MySQL Cluster, pero para obtener una introducción formal a la arquitectura, se puede consultar el siguiente enlace:
http://dev.mysql.com/doc/refman/5.1/en/mysql-cluster.html
La configuración y pruebas son únicamente para ejemplificar el uso por lo que se realizarán sobre un único servidor conformado por el host y 3 jaulas. Los datos asociados son los siguientes:
172.20.90.171 host 172.20.90.172 jail1 172.20.90.173 jail2 172.20.90.174 jail3
La versión utilizada de MySQL será la 5.1 (disponible en los ports) y mysql-cluster 7.0.8a (disponible en un port independiente).
Instalación
Lo primero que hay que hacer es instalar el servidor y el cliente de MySQL, en este caso vamos a generar los paquetes, mismos que se instalarán en las jaulas.
cd /usr/ports/databases/mysql51-client && make -DWITH_NDB package cd /usr/ports/databases/mysql51-server && make -DWITH_NDB package
Los paquetes se generarán en el directorio /usr/ports/packages/All/mysql-*.tbz.
El parametro -DWITH_NDB agrega el soporte del engine NDB que es el encargado de las funciones de clustering.
Aquí es importante mencionar que la versión 5.1 de MySQL incluye NDB 5.x, una versión descontinuada, limitada, y que al menos a mi, me dio problemas de funcionamiento.
Para solucionar este problema lo que haremos será instalar el port mysql-cluster, disponible este enlace. También hay que descargar este paquete que contiene el código fuente del cluster.
A continuación la lista de comandos a ejecutar:
fetch http://downloads.mysql.com/archives/mysql-cluster-gpl-7.0/mysql-cluster-gpl-7.0.8a.tar.gz mv mysql-cluster-gpl-7.0.8a.tar.gz /usr/ports/distfiles fetch http://www.alexdupre.com/mysql-cluster.tar.gz tar xzf mysql-cluster.tar.gz && cd mysql-cluster && make package
Es importante destacar que mysql-cluster tiene que ser instalado al final para que con esto se sobreescriban los archivos relacionados al engine NDB, de lo contrario seguiremos utilizando la versión 5.x y el cluster funcionara incorrectamente.
También hay que remplazar el texto "%%RC_SUBR%%" por "/etc/rc.subr" en el archivo /usr/local/etc/rc.d/mysql-server, de lo contrario el demonio MySQL no podrá iniciarse.
Una vez generados los paquetes, el siguiente paso es instalarlos en las jaulas.
Para este paso hay que copiar los paquetes en cada una de las jaulas, y luego los instalaremos con los siguientes comandos:
pkg_add mysql-client-5.1.X.tbz pkg_add mysql-server-5.1.X.tbz pkg_add mysql-cluster-7.0.8a.tbz
Al igual que con el host, el paquete mysql-cluster tiene que instalarse al final para sobreescribir los archivos del motor NDB, y también va a ser necesario actualizar el script /usr/local/etc/rc.d/mysql-server.
Configuración
Toda la información relacionada al cluster la mantendremos en los directorios /usr/local/mysql-cluster y /usr/local/mysql-cluster/data, por lo cual previamente hay que crearlos en el host y las jaulas.
Lo primero que configuraremos será el servidor de administración, en este caso el host, la configuración la guardaremos en el archivo /usr/local/mysql-cluster/config.ini. A continuación una parte del contenido:
[ndbd default] noofreplicas=3 datadir=/usr/local/mysql-cluster/data datamemory=512M indexmemory=10M [ndb_mgmd] id=1 hostname=172.20.90.171 [ndbd] id=3 hostname=172.20.90.172 [ndbd] id=4 hostname=172.20.90.173 [ndbd] id=5 hostname=172.20.90.174 [mysqld] id=6 hostname=172.20.90.172 [mysqld] id=7 hostname=172.20.90.173 [mysqld] id=8 hostname=172.20.90.174
El contenido esta basado en la sintaxis de un archivo ini estandar, con lo que se entiende que lo esta encerrado entre corchetes son secciones, y los valores siguientes son las opciones de configuración.
"ndbd default" es donde se mantienen los valores por defecto para los nodos. noofreplicas sirve para especificar el número de replicas que utilizaremos.
"ndb_mgmd" contiene la configuración del servidor administrativo, en este caso solo definiremos su identificador y la dirección asociada al servicio.
"ndbd" sirve para especificar un nodo del cluster, en este caso solo estamos especificando el id y la dirección desde donde se conectará el nodo. Cada una de las definiciones "[ndbd]" representa un único nodo.
"mysqld" especifica los servidores SQL y desde donde se conectaran, en estos servidores se ejecutaran los servicios mysql y es a donde se conectaran los clientes.
Una idea interesante es no especificar el hosname ni el id y permitir así que cualquier servidor sql se conecte al servidor administrativo y sea utilizado.
El siguiente paso es habilitar el engine ndbcluster en mysql, esto se logra agregando la opción "ndbcluster" en la sección [mysqld] del archivo /etc/my.cnf. A continuación un ejemplo de dicho archivo:
[mysqld] ndbcluster
El último paso es ejecutar el demonio del servicio con el siguiente comando:
/usr/local/libexec/ndb_mgmd -f /usr/local/mysql-cluster/config.ini
Para verificar que el servicio esta en ejecución, hay que utilizar el siguiente comando:
ndb_mgm -e show
Con lo que obtendremos una salida similar a la siguiente:
Connected to Management Server at: 172.20.90.171:1186 Cluster Configuration --------------------- [ndbd(NDB)] 3 node(s) id=3 (not connected, accepting connect from 172.20.90.172) id=4 (not connected, accepting connect from 172.20.90.173) id=5 (not connected, accepting connect from 172.20.90.174) [ndb_mgmd(MGM)] 1 node(s) id=1 @172.20.90.171 (mysql-5.1.37 ndb-7.0.8) [mysqld(API)] 3 node(s) id=6 (not connected, accepting connect from 172.20.90.172) id=7 (not connected, accepting connect from 172.20.90.173) id=8 (not connected, accepting connect from 172.20.90.174)
El siguiente paso es configurar los nodos mediante el archivo /etc/my.cnf, las siguiente lineas ejemplifican la configuración:
[mysqld] ndbcluster ndb-connectstring=172.20.90.171 [mysql_cluster] ndb-connectstring=172.20.90.171
También hay que habilitar el servidor MySQL en en FreeBSD, esto se logra agregando la siguiente linea al archivo /etc/rc.conf.
mysql_enable="YES"
Y para terminar, solo resta ejecutar el demonio de conexión de los nodos y los servidores sql utilizando los siguientes comandos:
/usr/local/libexec/ndbd --initial /usr/local/etc/rc.d/mysql-server start
Hay que destacar que el parametro --initial solo se debe de utilizar cuando se inicializa el nodo, la primera vez.
Una vez realizado todo lo anterior, sí ejecutamos el comando "ndb_mgm -e show" en el nodo administrativo, debemos obtener una salida similar a la siguiente:
Connected to Management Server at: 172.20.90.171:1186 Cluster Configuration --------------------- [ndbd(NDB)] 3 node(s) id=3 @172.20.90.172 (mysql-5.1.37 ndb-7.0.8, Nodegroup: 0, Master) id=4 @172.20.90.173 (mysql-5.1.37 ndb-7.0.8, Nodegroup: 0) id=5 @172.20.90.174 (mysql-5.1.37 ndb-7.0.8, Nodegroup: 0) [ndb_mgmd(MGM)] 1 node(s) id=1 @172.20.90.171 (mysql-5.1.37 ndb-7.0.8) [mysqld(API)] 3 node(s) id=6 @172.20.90.172 (mysql-5.1.37 ndb-7.0.8) id=7 @172.20.90.173 (mysql-5.1.37 ndb-7.0.8) id=8 @172.20.90.174 (mysql-5.1.37 ndb-7.0.8)
Que muestra que todos los nodos están conectados y funcionando.
Pasos finales
Para probar que el cluster funciona correctamente, desde cualquier nodo se puede crear una tabla que utilice el engine ndbcluster, e insertar datos en ella, por ejemplo:
mysql
mysql> USE test; mysql> CREATE TABLE prueba (id INT auto_increment PRIMARY KEY) ENGINE=ndbcluster; mysql> INSERT INTO prueba () VALUES (0); mysql> INSERT INTO prueba () VALUES (0); mysql> INSERT INTO prueba () VALUES (0);
Y desde cualquier otro nodo ejecutar un SELECT, que nos devería devolver una salida similar a la siguiente:
mysql
mysql> SELECT * FROM prueba ORDER BY id; +----+ | id | +----+ | 1 | | 2 | | 3 | | 4 | | 5 |
Parte de nuestras pruebas deben incluir el retirar nodos, agregar nuevos nodos, y ver que todo se replique correctamente, pero esos ejercicios quedan a consideración del lector.
Conclusión
MySQL en combinación con MySQL Cluster, forman sin duda una excelente solución para brindar servicios alta disponibilidad y escalabilidad. Es útil para todo tipo de empresas, desde pequeñas que están en crecimiento y que solo requiren unos cuantos nodos, hasta empresas tan grandes como Facebook, que constantemente requieren agregar nodos para incrementar su disponibilidad y tiempo de respuesta.
Autor
Angel Gabriel León Rodríguez