systemadmin.es » DBA » Instalación de MySQL Cluster (ndb)

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 Imprimir

2 comments to “Instalación de MySQL Cluster (ndb)”

  1. 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

  2. Para desplegar esta muy bien, muy cómodo

    Muchas gracias por la aportación!

Deja un comentario:

XHTML - Tags permitidos:<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>