Instalación de MySQL Cluster (ndb)
Vamos a ver como instalar MySQL Cluster y sus características. No se trata de una solución de alta disponibilidad para el típico MySQL (con tablas MyISAM o InnoDB) sino que se trata de un storage engine transaccional con sus propias características: ndb
El MySQL Cluster ndb ofrece una base de datos sin nada compartido con tres tipos de nodos diferenciados:
- Nodo de gestión (ndb_mgmd): Permite la gestión del resto de nodos del cluster, arrancar y apagar nodos o hacer backups. Aunque se deba arrancar el primero puede fallar sin afectar al funcionamiento del cluster.
- Nodo de datos (ndbd o ndbmtd): Almacena los datos los trata
- Nodo SQL: Nodo a través del cual accedemos a los datos. Se trata de un mysqld con el conector para los ndb. Debe ser arrancado con las opciones ndbcluster para habilitar el storage engine y la opción ndb-connectstring para indicar el nodo a conectarnos para acceder al clúster
Tiene algunas restricciones a considerar:
- Se trata de una base de datos en memoria por lo que tantos datos por tanta redundacia es la memória RAM que necesitamos (más un extra por el sistema y los deamons). En las versiones actuales los datos no indexados pueden ir a disco pero todo dato indexado debe estar en memoria.
- Las queries con joins al estar repartidas las rows entre los nodos de datos pasar a ser, en general, más costosas. Lo ideal es obtener siempre resulsets pequeños
- El storage engine no soporta foreign keys. La aplicación no debe depender de éstas para mantener la consisténcia
- El storage engine no soporta FULLTEXT, por lo que para este tipo de búsquedas es posible que necesitemos un sistema externo como solr o Sphinx
A continuación podemos ver como instalar el MySQL Cluster en un solo equipo para evaluarlo. Para la instalación podemos bajar los binarios de la web de MySQL y dejarlos en /opt/mysql-cluster:
cd /usr/local/src wget http://dev.mysql.com/get/Downloads/MySQL-Cluster-7.1/mysql-cluster-gpl-7.1.15a-linux-x86_64-glibc23.tar.gz/from/http://mirrors.ircam.fr/pub/mysql/ tar xzf mysql-cluster-gpl-7.1.15a-linux-x86_64-glibc23.tar.gz -C /opt ln -s /opt/mysql-cluster-gpl-7.1.15a-linux-x86_64-glibc23/ /opt/mysql-cluster
A continuación añadimos el usuario mysql:
groupadd mysql useradd -g mysql mysql
Y cambiamos permisos:
cd /opt/mysql-cluster chown -R root:mysql .
Podemos crear los directorios para el cluster de evaluación dentro de /opt/mycluster:
mkdir -p /opt/mycluster/conf mkdir -p /opt/mycluster/ndb1 mkdir -p /opt/mycluster/ndb2 mkdir -p /opt/mycluster/ndb3 mkdir -p /opt/mycluster/ndb4 mkdir -p /opt/mycluster/mysqld mkdir -p /opt/mycluster/ndb-mgm chown mysql. /opt/mycluster/ndb1 chown mysql. /opt/mycluster/ndb2 chown mysql. /opt/mycluster/ndb3 chown mysql. /opt/mycluster/ndb4 chown mysql. /opt/mycluster/mysqld chown mysql. /opt/mycluster/ndb-mgm
En un entorno real depende del rol del equipo creariamos un directorio o otro. A continuación instalaremos las tablas para el mysqld:
cd /opt/mysql-cluster ./scripts/mysql_install_db --user=mysql --datadir=/opt/mycluster/mysqld
Seguimos definiendo un my.cnf muy básico
cat <<EOF > /opt/mycluster/conf/my.cnf [mysqld] ndbcluster datadir=/opt/mycluster/mysqld basedir=/opt/mysql-cluster EOF
Y la configuración básica del cluster con redundancia 2:
cat <<EOF > /opt/mycluster/conf/config.ini [ndb_mgmd] hostname=localhost datadir=/opt/mycluster/ndb-mgm nodeid=1 [ndbd default] noofreplicas=2 [ndbd] hostname=localhost datadir=/opt/mycluster/ndb1 nodeid=11 [ndbd] hostname=localhost datadir=/opt/mycluster/ndb2 nodeid=12 [mysqld] nodeid=50 EOF
Cambiamos los permisos:
chown mysql. /opt/mycluster/conf/ -R
Y arrancamos el nodo de management:
su - mysql -c '/opt/mysql-cluster/bin/ndb_mgmd -f /opt/mycluster/conf/config.ini --initial --configdir=/opt/mycluster/conf/'
Podemos ver que el nodo de gestión esta arrancado con netstat. Veremos que esta escuchando, por defecto, en el puerto 1186:
# netstat -tpln | grep ndb_mgmd tcp 0 0 0.0.0.0:1186 0.0.0.0:* LISTEN 30375/ndb_mgmd
A continuación podemos arrancar el primer nodo de datos:
su - mysql -c '/opt/mysql-cluster/bin/ndbmtd -c localhost:1186'
Veremos como nos indica como arranca y que nodeid obtiene:
2011-10-17 15:56:55 [ndbd] INFO -- Angel connected to 'localhost:1186' 2011-10-17 15:56:55 [ndbd] INFO -- Angel allocated nodeid: 11
Si volvemos a ejecutar el comando:
su - mysql -c '/opt/mysql-cluster/bin/ndbmtd -c localhost:1186'
Dada la configuración que hemos definido sin restringir por host, obtendremos el siguiente nodeid disponible:
2011-10-17 15:57:44 [ndbd] INFO -- Angel connected to 'localhost:1186' 2011-10-17 15:57:44 [ndbd] INFO -- Angel allocated nodeid: 12
Mediante ndb_mgm y la opción -e para pasar comandos podemos ver datos sobre el estado del cluster y sus nodos. Con SHOW veremos un resumen del estado global:
# /opt/mysql-cluster/bin/ndb_mgm -e show Connected to Management Server at: localhost:1186 Cluster Configuration --------------------- [ndbd(NDB)] 2 node(s) id=11 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15, Nodegroup: 0, Master) id=12 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15, Nodegroup: 0) [ndb_mgmd(MGM)] 1 node(s) id=1 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15) [mysqld(API)] 1 node(s) id=50 (not connected, accepting connect from any host)
A continuación podemos arrancar el mysqld:
su - mysql -c '/opt/mysql-cluster/bin/mysqld --defaults-file=/opt/mycluster/conf/my.cnf '
Veremos como arranca y conecta con los nodos de datos ndb:
111017 16:01:17 [Note] Plugin 'FEDERATED' is disabled. 111017 16:01:17 InnoDB: Initializing buffer pool, size = 8.0M 111017 16:01:17 InnoDB: Completed initialization of buffer pool InnoDB: The first specified data file ./ibdata1 did not exist: InnoDB: a new database to be created! 111017 16:01:17 InnoDB: Setting file ./ibdata1 size to 10 MB InnoDB: Database physically writes the file full: wait... 111017 16:01:18 InnoDB: Log file ./ib_logfile0 did not exist: new to be created InnoDB: Setting log file ./ib_logfile0 size to 5 MB InnoDB: Database physically writes the file full: wait... 111017 16:01:18 InnoDB: Log file ./ib_logfile1 did not exist: new to be created InnoDB: Setting log file ./ib_logfile1 size to 5 MB InnoDB: Database physically writes the file full: wait... InnoDB: Doublewrite buffer not found: creating new InnoDB: Doublewrite buffer created InnoDB: Creating foreign key constraint system tables InnoDB: Foreign key constraint system tables created 111017 16:01:18 InnoDB: Started; log sequence number 0 0 111017 16:01:18 [Note] NDB: NodeID is 50, management server 'localhost:1186' 111017 16:01:18 [Note] NDB[0]: NodeID: 50, all storage nodes connected 111017 16:01:18 [Warning] NDB: server id set to zero - changes logged to bin log with server id zero will be logged with another server id by slave mysqlds 111017 16:01:18 [Note] Starting Cluster Binlog Thread 111017 16:01:18 [Note] Event Scheduler: Loaded 0 events 111017 16:01:19 [Note] NDB: Creating mysql.ndb_schema 111017 16:01:20 [Note] NDB Binlog: CREATE TABLE Event: REPL$mysql/ndb_schema 111017 16:01:20 [Note] NDB Binlog: logging ./mysql/ndb_schema (UPDATED,USE_WRITE) 111017 16:01:20 [Note] NDB: Creating mysql.ndb_apply_status 111017 16:01:20 [Note] NDB Binlog: CREATE TABLE Event: REPL$mysql/ndb_apply_status 111017 16:01:20 [Note] NDB Binlog: logging ./mysql/ndb_apply_status (UPDATED,USE_WRITE) 2011-10-17 16:01:20 [NdbApi] INFO -- Flushing incomplete GCI:s < 102/18 2011-10-17 16:01:20 [NdbApi] INFO -- Flushing incomplete GCI:s < 102/18 111017 16:01:20 [Note] NDB Binlog: starting log at epoch 102/18 111017 16:01:20 [Note] NDB Binlog: ndb tables writable 111017 16:01:20 [Note] /opt/mysql-cluster/bin/mysqld: ready for connections. Version: '5.1.56-ndb-7.1.15a-cluster-gpl' socket: '/tmp/mysql.sock' port: 3306 MySQL Cluster Server (GPL)
Obtendremos el mysqld en el puerto por defecto al que podemos conectar normalmente como cualquier otro MySQL:
# netstat -tpln | grep mysqld tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 9534/mysqld
Con ndb_mgm podemos ver que ya tenemos el cluster completo:
# /opt/mysql-cluster/bin/ndb_mgm -e show Connected to Management Server at: localhost:1186 Cluster Configuration --------------------- [ndbd(NDB)] 2 node(s) id=11 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15, Nodegroup: 0, Master) id=12 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15, Nodegroup: 0) [ndb_mgmd(MGM)] 1 node(s) id=1 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15) [mysqld(API)] 1 node(s) id=50 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15)
Para crear las tablas ndb simplemente deberemos indicar ENGINE=ndb, por ejemplo:
[root@apolo src]# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 Server version: 5.1.56-ndb-7.1.15a-cluster-gpl MySQL Cluster Server (GPL) Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> create database jordi; Query OK, 1 row affected (0.06 sec) mysql> use jordi; Database changed mysql> create table jordi(id int) engine=ndb; Query OK, 0 rows affected (0.06 sec) mysql> insert into jordi values (1),(2),(3); Query OK, 3 rows affected (0.00 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> select * from jordi; +------+ | id | +------+ | 1 | | 3 | | 2 | +------+ 3 rows in set (0.00 sec) mysql>
En el log del mysqld podemos ver que se ha creado la tabla:
111017 16:04:16 [Note] NDB Binlog: CREATE TABLE Event: REPL$jordi/jordi
Y en el datadir tendremos la base de datos:
# ls -la /opt/myclusterdb/ total 20548 drwxr-xr-x 6 mysql mysql 4096 Oct 17 16:03 . drwxr-xr-x 7 root root 4096 Oct 17 15:21 .. -rw-rw---- 1 mysql mysql 5 Oct 17 16:01 apolo.pid -rw-rw---- 1 mysql mysql 10485760 Oct 17 16:01 ibdata1 -rw-rw---- 1 mysql mysql 5242880 Oct 17 16:01 ib_logfile0 -rw-rw---- 1 mysql mysql 5242880 Oct 17 16:01 ib_logfile1 drwx------ 2 mysql mysql 4096 Oct 17 16:04 jordi drwx------ 2 mysql root 4096 Oct 17 16:01 mysql drwx------ 2 mysql mysql 4096 Oct 17 13:54 ndbinfo drwx------ 2 mysql root 4096 Oct 17 13:54 test
Los privilegios se almacenan en el datadir del mysqld, por lo que deberemos definirlos a cada uno que instalemos con sus usuarios:
pwgen 20 > /opt/myclusterdb/.mysql.root.pass chmod 600 /opt/myclusterdb/.mysql.root.pass /opt/mysql-cluster/bin/mysqladmin -u root -h 127.0.0.1 password $(cat /opt/myclusterdb/.mysql.root.pass) /opt/mysql-cluster/bin/mysqladmin -u root password $(cat /opt/myclusterdb/.mysql.root.pass) echo "alias mycluster='/opt/mysql-cluster/bin/mysql -p\$(cat /opt/myclusterdb/.mysql.root.pass)'" >> /etc/profile . /etc/profile echo 'delete from mysql.user where Password="";' | mycluster echo 'flush privileges;' | mycluster
Podemos hacer algunas pruebas matando los ndb:
# kill 28420 28419 25273 25272 # kill 28420 28419 25273 25272 -bash: kill: (28420) - No such process -bash: kill: (28419) - No such process -bash: kill: (25273) - No such process -bash: kill: (25272) - No such process
Veremos en el log como desparecen:
111017 16:17:43 [Note] NDB Binlog: Node: 11, down, Subscriber bitmask 00 111017 16:17:43 [Note] NDB Binlog: Node: 12, down, Subscriber bitmask 00 111017 16:17:43 [Note] NDB Binlog: cluster failure for ./mysql/ndb_schema at epoch 585/0. 111017 16:17:43 [Note] NDB Binlog: cluster failure for ./mysql/ndb_apply_status at epoch 585/0. 111017 16:17:43 [Note] Restarting Cluster Binlog
Como ha perdido los nodos de datos ya no podremos hacer queries a la tabla:
mysql> select * from jordi; ERROR 1296 (HY000): Got error 157 'Unknown error code' from NDBCLUSTER
Y en el ndb_mgm los veremos como not connected:
# /opt/mysql-cluster/bin/ndb_mgm -e show Connected to Management Server at: localhost:1186 Cluster Configuration --------------------- [ndbd(NDB)] 2 node(s) id=11 (not connected, accepting connect from localhost) id=12 (not connected, accepting connect from localhost) [ndb_mgmd(MGM)] 1 node(s) id=1 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15) [mysqld(API)] 1 node(s) id=50 (not connected, accepting connect from any host)
Arrancando de nuevo los nodos:
# su - mysql -c '/opt/mysql-cluster/bin/ndbmtd -c localhost:1186' 2011-10-17 16:18:50 [ndbd] INFO -- Angel connected to 'localhost:1186' 2011-10-17 16:18:50 [ndbd] INFO -- Angel allocated nodeid: 11 # su - mysql -c '/opt/mysql-cluster/bin/ndbmtd -c localhost:1186' 2011-10-17 16:18:53 [ndbd] INFO -- Angel connected to 'localhost:1186' 2011-10-17 16:18:53 [ndbd] INFO -- Angel allocated nodeid: 12
Vemos que reaparecen en el ndb_mgm:
# /opt/mysql-cluster/bin/ndb_mgm -e show Connected to Management Server at: localhost:1186 Cluster Configuration --------------------- [ndbd(NDB)] 2 node(s) id=11 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15, Nodegroup: 0, Master) id=12 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15, Nodegroup: 0) [ndb_mgmd(MGM)] 1 node(s) id=1 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15) [mysqld(API)] 1 node(s) id=50 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15)
Y en el mysqld los volvemos a ver:
111017 16:19:03 [Note] NDB Binlog: DISCOVER TABLE Event: REPL$mysql/ndb_schema 111017 16:19:03 [Note] NDB Binlog: logging ./mysql/ndb_schema (UPDATED,USE_WRITE) 111017 16:19:03 [Note] NDB Binlog: DISCOVER TABLE Event: REPL$mysql/ndb_apply_status 111017 16:19:04 [Note] NDB Binlog: logging ./mysql/ndb_apply_status (UPDATED,USE_WRITE) 2011-10-17 16:19:04 [NdbApi] INFO -- Flushing incomplete GCI:s < 585/14 2011-10-17 16:19:04 [NdbApi] INFO -- Flushing incomplete GCI:s < 585/14 111017 16:19:04 [Note] NDB Binlog: starting log at epoch 585/14 111017 16:19:04 [Note] NDB Binlog: ndb tables writable
Y podremos volver a acceder a los datos ya que periódicamente los ndb pasan los datos a disco.
mysql> select * from jordi; +------+ | id | +------+ | 3 | | 2 | | 1 | +------+ 3 rows in set (0.12 sec)
Incluso matando todos los daemons:
[root@apolo src]# kill 30375 9534 [root@apolo src]# kill 30375 9534 -bash: kill: (30375) - No such process [root@apolo src]# kill 30375 9534 -bash: kill: (30375) - No such process [root@apolo src]# kill 30375 9534 -bash: kill: (30375) - No such process -bash: kill: (9534) - No such process
Al volver a arrancar:
# su - mysql -c '/opt/mysql-cluster/bin/ndb_mgmd -f /opt/mycluster/conf/config.ini --initial --configdir=/opt/mycluster/conf/' # su - mysql -c '/opt/mysql-cluster/bin/mysqld --defaults-file=/opt/mycluster/conf/my.cnf ' # su - mysql -c '/opt/mysql-cluster/bin/ndbmtd -c localhost:1186' 2011-10-17 16:23:18 [ndbd] INFO -- Angel connected to 'localhost:1186' 2011-10-17 16:23:18 [ndbd] INFO -- Angel allocated nodeid: 11 # su - mysql -c '/opt/mysql-cluster/bin/ndbmtd -c localhost:1186' 2011-10-17 16:23:19 [ndbd] INFO -- Angel connected to 'localhost:1186' 2011-10-17 16:23:19 [ndbd] INFO -- Angel allocated nodeid: 12
Tendremos de nuevo los datos:
# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 Server version: 5.1.56-ndb-7.1.15a-cluster-gpl MySQL Cluster Server (GPL) Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> use jordi Database changed mysql> select * from jordi; +------+ | id | +------+ | 1 | | 3 | | 2 | +------+ 3 rows in set (0.05 sec) mysql>
Evidentemente se trata de un entorno de pruebas sin transacciones activas, por lo que no debemos hacer estas cosas en un mysql de producción si no queremos perder transacciones.
Relacionados
Imprimir
10. January 2012 at 10:49 am :
Para montar un cluster de MySQL, …hay maneras de hacerlo fácil.
http://www.severalnines.com/resources/configurator
Ese configurador ya te genera todo lo necesario para optimizarlo, etc.
Los creó Johan Andersson, un consultor de clusters de MySQL para acelerar su trabajo diario. Los compartió con la comunidad, y luego, su empresa los sigue haciendo gratuitos.
Te arreglan la vida
Kitai
Gigas.com
11. January 2012 at 10:15 am :
Para desplegar esta muy bien, muy cómodo
Muchas gracias por la aportación!