¿Qué es Percona XtraDB Cluster?
Percona XtraDB Cluster es una versión avanzada de MySQL que permite que múltiples servidores de bases de datos trabajen juntos como un solo "clúster". Imagina que tienes varias computadoras (servidores) que actúan como una única base de datos. El propósito principal de este clúster es ofrecer alta disponibilidad y replicación de datos en tiempo real.
¿Por qué usar un clúster de bases de datos?
En desarrollo, a veces una sola base de datos puede no ser suficiente por varias razones:
- Escalabilidad: Si tienes muchos usuarios y una sola base de datos, el servidor puede saturarse. Un clúster permite distribuir la carga entre múltiples servidores.
- Disponibilidad: Si la única base de datos falla, tu aplicación se detiene. Con un clúster, los datos se replican entre varios servidores, por lo que si uno falla, los demás continúan funcionando.
- Seguridad de datos: Al tener los datos replicados en varios servidores, reduces el riesgo de pérdida de datos.
¿Cómo funciona Percona XtraDB Cluster?
Para entender cómo funciona, imagina un equipo de personas trabajando en un documento compartido:
- Replicación en tiempo real: Cuando uno de los servidores (nodos) recibe una solicitud para agregar, modificar o eliminar datos, esta información se copia automáticamente a los demás servidores del clúster. Es como si varias personas estuvieran editando el mismo documento y cada cambio se sincronizara inmediatamente para que todos vean lo mismo.
- Todos los nodos son iguales: En un clúster de Percona, todos los servidores (nodos) pueden realizar operaciones de lectura y escritura. No hay un "servidor principal" y un "servidor secundario" como en otros sistemas. Esto significa que puedes distribuir las solicitudes de tu aplicación entre los diferentes nodos para mejorar la velocidad y eficiencia.
- Consenso y sincronización: Percona XtraDB Cluster usa un mecanismo llamado Galera para asegurarse de que todos los nodos estén sincronizados. Si un nodo recibe una solicitud para insertar datos, ese cambio debe ser aprobado por los demás nodos antes de aplicarse. Esto garantiza que los datos sean coherentes en todos los servidores.
- Fallos y recuperación: Si un nodo falla, el clúster sigue funcionando con los demás nodos. Cuando el nodo caído se reinicia, automáticamente se sincroniza con el resto del clúster para recuperar los datos que se perdió mientras estuvo desconectado.
¿Cómo se configura Percona XtraDB Cluster en términos simples?
- Nodos: Un clúster de Percona está formado por varios nodos. Cada nodo es básicamente una instancia de MySQL que está configurada para sincronizar datos con los demás nodos.
- Replicación: Al escribir o actualizar datos en uno de los nodos, esos cambios se replican a los otros nodos casi inmediatamente.
- Balanceo de carga: En tu aplicación, puedes configurar las operaciones de lectura y escritura para que se distribuyan entre los nodos. Por ejemplo, puedes configurar que todas las escrituras se hagan en un nodo específico y que las lecturas se distribuyan entre los demás nodos.
1. Crear contenedores de Docker
Para poder seguir los pasos del manual sera necesario tener instalado docker previamente, si aun lo has hecho puedes consultar la documentación oficial para tu sistema operativo. Install Docker Engine
1.1 Crear archivos Dockerfile
y docker-compose.yml
Creamos una carpeta llamada percona-xdb-cluster
mkdir percona-xdb-cluster
Nos posicionamos dentro de la carpeta y creamos el archivo Dockerfile
y docker-compose.yml
Pegamos el siguiente contenido dentro de nuestro Dockerfile
# Dockerfile
# Usar la imagen base de Ubuntu 20.04
FROM ubuntu:20.04
# Establecer el entorno no interactivo para evitar prompts durante la instalación
ENV DEBIAN_FRONTEND=noninteractive
# Exponer el puerto 3306 para MySQL
EXPOSE 3306
Creamos el archivo docker-compose.yml
Pegamos el siguiente contenido dentro de nuestro docker-compose.yml
version: '3.8'
services:
mysql-server-1:
build:
context: .
dockerfile: Dockerfile
container_name: mysql-server-1
hostname: node-1
networks:
custom_network:
ipv4_address: 172.20.0.3
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- mysql1_data:/var/lib/mysql
ports:
- "3308:3306" # Mapeo de puerto para acceso externo
#command: mysqld_safe
command: bash -c "tail -f /dev/null"
mysql-server-2:
build:
context: .
dockerfile: Dockerfile
container_name: mysql-server-2
hostname: node-2
networks:
custom_network:
ipv4_address: 172.20.0.4
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- mysql2_data:/var/lib/mysql
ports:
- "3309:3306" # Mapeo de puerto para acceso externo
# command: mysqld_safe
command: bash -c "tail -f /dev/null"
mysql-server-3:
build:
context: .
dockerfile: Dockerfile
container_name: mysql-server-3
hostname: node-3
networks:
custom_network:
ipv4_address: 172.20.0.5
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- mysql3_data:/var/lib/mysql
ports:
- "3310:3306" # Mapeo de puerto para acceso externo
# command: mysqld_safe
command: bash -c "tail -f /dev/null"
networks:
custom_network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
volumes:
proxy_data:
mysql1_data:
mysql2_data:
mysql3_data:
1.2 Levantar contenedores
Levantamos los contenedores usando el siguiente comando
docker compose up --build
1.3 Comprobación
Una vez hecho esto deberiampos poder nuestros contenedores usando el siguiente comando
La salida del comando deberia ser algo similar a esto
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e57dde592d32 dokcer-cluster-mysql-mysql-server-1 "bash -c 'tail -f /d…" 3 hours ago Up 3 hours 4444/tcp, 4567-4568/tcp, 0.0.0.0:3308->3306/tcp mysql-server-1
1ac0df8488c3 dokcer-cluster-mysql-mysql-server-2 "bash -c 'tail -f /d…" 3 hours ago Up 3 hours 4444/tcp, 4567-4568/tcp, 0.0.0.0:3309->3306/tcp mysql-server-2
191806016fff dokcer-cluster-mysql-mysql-server-3 "bash -c 'tail -f /d…" 3 hours ago Up 3 hours 4444/tcp, 4567-4568/tcp, 0.0.0.0:3310->3306/tcp mysql-server-3
f448ea10cc7f dokcer-cluster-mysql-proxysql "bash -c 'tail -f /d…" 3 hours ago Up 3 hours 4444/tcp, 4567-4568/tcp, 0.0.0.0:3307->3306/tcp mysql-proxysql
2. Instalar Percona XtraDB Cluster
Una vez que tengamos nuestro contenedores corriendo, procedemos a configurar, para ello realizaremos los pasos descritos en Implementar Percona Cluster - Parte 1, en este caso omitiremos la instalación del proxy, trabajaremos unicamente con los nodos
Para acceder a nuestro primer nodo usamos el siguiente comando
docker exec -it <id_contenedor> bash
# Ejemplo:
docker exec -it e57dde592d32 bash
Una vez hayamos accedido a nuestro contenedor realizamos la instalación de Percona XtraDB Cluster
# Actualizamos nuestro sistema
apt-get update
# Instalamos wget, lsb-release, gnup y curl
apt-get install -y wget lsb-release gnupg curl systemctl nano htop tree net-tools
# Actualizamos nuevamente
apt update
wget https://repo.percona.com/apt/percona-release_latest.generic_all.deb
dpkg -i percona-release_latest.generic_all.deb
percona-release setup pxc57
apt install -y libdbi-perl libdbd-mysql-perl libmecab2 socat libcurl4-openssl-dev libev4
apt install -y percona-xtrabackup-24 qpress
apt install -y percona-xtradb-cluster-full-57=5.7.40-31.63-1.focal percona-xtradb-cluster-server-5.7=5.7.40-31.63-1.focal percona-xtradb-cluster-client-5.7=5.7.40-31.63-1.focal percona-xtradb-cluster-test-5.7=5.7.40-31.63-1.focal percona-xtradb-cluster-5.7-dbg=5.7.40-31.63-1.focal percona-xtradb-cluster-server-debug-5.7=5.7.40-31.63-1.focal percona-xtradb-cluster-garbd-5.7=5.7.40-31.63-1.focal percona-xtradb-cluster-garbd-debug-5.7=5.7.40-31.63-1.focal percona-xtradb-cluster-common-5.7=5.7.40-31.63-1.focal
Repetimos los pasos en nuestros nodos restantes
3. Configuración de los nodos
3.1 Configuración de los nodos
Para acceder a nuestro primer nodo usamos el siguiente comando
docker exec -it <id_contenedor> bash
# Ejemplo:
docker exec -it e57dde592d32 bash
Una vez dentro de nuestro contenedor configuramos el archivo wsrep.cnf
nano /etc/mysql/percona-xtradb-cluster.conf.d/wsrep.cnf
Usamos nano como editor para poder modificar nuestros archivos, sin embargo, nano no viene instalado por defecto, para instalarlo podemos usar el siguiente comando `apt-get install nano`
Modificaremos unicamente lo siguiente:
wsrep_cluster_address=gcomm://<ip_nodos_cluster>
wsrep_node_address=<ip_nodo>
wsrep_node_name=<nombre_nodo>
pxc_strict_mode=PERMISSIVE
wsrep_sst_auth="sstuser:<my_secure_password>"
Nuestro archivos deberian verse de la siguiente manera en cada nodo
Nodo 1:
[mysqld]
# Path to Galera library
wsrep_provider=/usr/lib/galera3/libgalera_smm.so
wsrep_cluster_address=gcomm://172.20.0.3,172.20.0.4,172.20.0.5 # IPs de los nodos que conforman el cluster
binlog_format=ROW
default_storage_engine=InnoDB
wsrep_slave_threads= 4
wsrep_log_conflicts
innodb_autoinc_lock_mode=2
wsrep_node_address=172.20.0.3 # IP del nodo que estamos configurando
wsrep_cluster_name=pxc-cluster
wsrep_node_name=Node-1 # Nombre de nuestro nodo, es importante que no se repita el nombre entre nodos
pxc_strict_mode=PERMISSIVE
wsrep_sst_method=xtrabackup-v2
wsrep_sst_auth="sstuser:my_secure_password"
Nodo 2:
[mysqld]
# Path to Galera library
wsrep_provider=/usr/lib/galera3/libgalera_smm.so
wsrep_cluster_address=gcomm://172.20.0.3,172.20.0.4,172.20.0.5 # IPs de los nodos que conforman el cluster
binlog_format=ROW
default_storage_engine=InnoDB
wsrep_slave_threads= 4
wsrep_log_conflicts
innodb_autoinc_lock_mode=2
wsrep_node_address=172.20.0.4 # IP del nodo que estamos configurando
wsrep_cluster_name=pxc-cluster
wsrep_node_name=Node-2 # Nombre de nuestro nodo, es importante que no se repita el nombre entre nodos
pxc_strict_mode=PERMISSIVE
wsrep_sst_method=xtrabackup-v2
wsrep_sst_auth="sstuser:my_secure_password"
Nodo 3:
[mysqld]
# Path to Galera library
wsrep_provider=/usr/lib/galera3/libgalera_smm.so
wsrep_cluster_address=gcomm://172.20.0.3,172.20.0.4,172.20.0.5 # IPs de los nodos que conforman el cluster
binlog_format=ROW
default_storage_engine=InnoDB
wsrep_slave_threads= 4
wsrep_log_conflicts
innodb_autoinc_lock_mode=2
wsrep_node_address=172.20.0.5 # IP del nodo que estamos configurando
wsrep_cluster_name=pxc-cluster
wsrep_node_name=Node-3 # Nombre de nuestro nodo, es importante que no se repita el nombre entre nodos
pxc_strict_mode=PERMISSIVE
wsrep_sst_method=xtrabackup-v2
wsrep_sst_auth="sstuser:my_secure_password"
Asegurate que en las variables wsrep_node_address
y wsrep_node_name
coloquemos la IP y nombre respectivamente del nodo que se este configurando, en el caso de la variable wsrep_sst_auth
es importante que coloquemos la misma contraseña,
3.2 Iniciar el primer nodo
Una vez que hemos finalizado al configuración de nuestros 3 nodos, accedemos al nodo 1 y lo inicializamos usando el siguiente comando
/etc/init.d/mysql bootstrap-pxc
Este comando iniciara nuestro nodo pero ademas indicara que es nuestro nodo principal
Una vez hecho esto accedemos a mysql
Podemos verificar el estado de nuestro cluster usando el siguiente comando
show status like 'wsrep%';
La salida del comando deberia ser algo similar a esto
+----------------------------+--------------------------------------+
| Variable_name | Value |
+----------------------------+--------------------------------------+
| wsrep_local_state_uuid | b598af3e-ace3-11e2-0800-3e90eb9cd5d3 |
| wsrep_local_state | 4 |
| wsrep_local_state_comment | Synced |
| wsrep_cluster_size | 1 |
| wsrep_cluster_status | Primary |
| wsrep_connected | ON |
| wsrep_ready | ON |
+----------------------------+--------------------------------------+
40 rows in set (0.01 sec)
Para realizar la transferencia de instantáneas de estado usando XtraBackup, configure un nuevo usuario con los privilegios adecuados
CREATE USER 'sstuser'@'%' IDENTIFIED BY 'my_secure_password';
GRANT RELOAD, LOCK TABLES, PROCESS, REPLICATION CLIENT ON *.* TO 'sstuser'@'%';
FLUSH PRIVILEGES;
El usuario debe crearse en el servidor que inicializara el Cluster. Para este caso, se crea en el Nodo 1
3.3 Iniciar el segundo y tercer nodo
Accedemos a los nodos 2 y 3 respectivamente y ejecutamos el siguiente comando
Eso inicializara nuestro nodo y deberia sincronizarse con nuestro nodo principal, nodo 1
Una vez se haya inicializado ingresamos a mysql y comprobamos el estado de nuestro cluster
show status like 'wsrep%';
La salida de nuestro comando ahora deberia mostrarnos que el tamaño del cluster ha cambiado, podemos observarlo en la variable wsrep_cluster_size
+----------------------------+--------------------------------------+
| Variable_name | Value |
+----------------------------+--------------------------------------+
| wsrep_local_state_uuid | b598af3e-ace3-11e2-0800-3e90eb9cd5d3 |
| wsrep_local_state | 4 |
| wsrep_local_state_comment | Synced |
| wsrep_cluster_size | 2 | -- El cluster size ha incrementado una vez iniciamos un nodo
| wsrep_cluster_status | Primary |
| wsrep_connected | ON |
| wsrep_ready | ON |
+----------------------------+--------------------------------------+
40 rows in set (0.01 sec)
Hasta este punto, ya tendras un Cluster de Base de Datos con Percona XtraDB Cluster.
La información se replica entre todos los nodos.
Puedes comprobarlo creando una base de datos.
4. Importar Base de Datos
4.1 Crear base de datos
Para poder realizar las pruebas podemos crear una base de datos con datos de prueba, para el ejercicio trabajaremos con la siguiente base de datos:
CompanyDB
Ingresamos a mysql y creamos una base de datos
Una vez hayamos accedido a mysql podemos crear la base de datos usando el siguiente comando
CREATE DATABASE companydb;
Salimos de mysql
Para poder importar la base de datos sera necesario agregarla al volumen de nuestro contenedor, puedes hacerlo de la siguiente forma en una nueva terminal:
docker docker cp /path/to/bdahkinc.sql mysql-server-1:/data/
Una vez la hayamos importado nos posicionamos en la ruta donde tengamos nuestro backup y ejectuamos el siguiente comando
mysql -u root -p companydb < backup.sql
Si te da error importar la base de datos, porque el collation no corresponde a tu version de MySQL, puede ejecutar lo siguiente:
sed -i 's/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g' backup.sql -> Actualizar la bd
4.2 Comprobación
Esto nos importara la información de la base de datos que creamos previamente, ademas, al tener configurados nuestros nodos deberia replicarse la información de nuestra base de datos, para ello podemos comprobarlo accediendo a mysql en alguno de nuestros nodos
Verificamos que tengamos la base de datos que creamos en el nodo 1
La salida del comando deberia mostrarnos la base de datos que creamos en el nodo 1
+--------------------+
| Database |
+--------------------+
| information_schema |
| companydb | -- Base de datos que creamos en el nodo 1
| mysql |
| performance_schema |
| sys |
+--------------------+
6 rows in set (0.00 sec)
Una vez que hayamos comprobado que tenemos nuestra base de datos en los tres nodos podemos realizar las pruebas, las pruebas que realizaremos seran las mismas que se hicieron en Implementar Percona Cluster - Parte 2
Al final el nodo que hemos creado se veria de la siguiente manera
La finalidad de esta prueba es agregar registros en uno de nuestros nodos, al encontrarse dentro de un cluster la información deberia replicarse a nuestros otros nodos.
5.1 Conectarse a cualquier nodo
docker exec -it <id_contenedor> bash
5.2 Para comprobar que todos los nodos estan conectados podemos hacer lo siguiente
5.2.1 Conectarse a mysql en los nodos
5.2.2 Conectarse a la base de datos
5.2.3 Verificamos en todos los nodos el ultimo ID
select * from Companies order by CompanyID DESC LIMIT 10 \G
5.2.4 Hacer inserciones en el nodo 1 (se puede realizar desde cualquier nodo):
INSERT INTO Companies (CompanyID, Name, Address, Phone, Email) VALUES (NULL, 'Other Company', 'Unit 5699 Box 8173 DPO AP 62802', '+1-635-243-2015x623', '[email protected]');
INSERT INTO Companies (CompanyID, Name, Address, Phone, Email) VALUES (NULL, 'Other Company', 'Unit 5699 Box 8173 DPO AP 62802', '+1-635-243-2015x623', '[email protected]');
INSERT INTO Companies (CompanyID, Name, Address, Phone, Email) VALUES (NULL, 'Other Company', 'Unit 5699 Box 8173 DPO AP 62802', '+1-635-243-2015x623', '[email protected]');
Creamos 3 registros en el nodo 1, al crearlo, la información debería reflejarse en los otros nodos
Volvemos a verificar los últimos IDs
5.3 En todos los nodos, verificamos que la información se este replicando correctamente:
select * from Companies order by CompanyID DESC LIMIT 10 \G
Podemos observar que la información se ha replicado correctamente
6. Reintegro de un Servidor Caído
La finalidad de esta prueba es que si uno de nuestros nodos esta caido/detenido, al momento de ponerse nuevamente en linea este deberia sincronizarse con nuestros nodos, esto quiere decir que la información deberia replicarse una vez que el nodo este nuevamente en linea.
En esta prueba podremos observar que sucede en caso de que uno de nuestros nodos se detenga, para ello lo que haremos sera detener mysql en alguno de nuestros nodos, posterior a eso crearemos registros, al levantar nuevamente nuestro nodo caido este deberia poder replicar la información creada
6.1 Detenemos mysql en cualquiera de nuestros nodos
Accedemos a uno de nuestros nodos de la siguiente manera
docker exec -it <id_contenedor> bash
Una vez hayamos accedido ejecutamos el siguiente comando
6.2 Insertamos registros
Hacer inserciones en cualquiera de los nodos sobrantes (Se pueden realizar desde cualquier nodo), accedemos a otro nodo:
docker exec -it <id_contenedor> bash
Ingresamos a mysql
Usamos nuestra base de datos
Agregamos registros
INSERT INTO Companies (CompanyID, Name, Address, Phone, Email) VALUES (NULL, 'Other Company', 'Unit 5699 Box 8173 DPO AP 62802', '+1-635-243-2015x623', '[email protected]');
INSERT INTO Companies (CompanyID, Name, Address, Phone, Email) VALUES (NULL, 'Other Company', 'Unit 5699 Box 8173 DPO AP 62802', '+1-635-243-2015x623', '[email protected]');
INSERT INTO Companies (CompanyID, Name, Address, Phone, Email) VALUES (NULL, 'Other Company', 'Unit 5699 Box 8173 DPO AP 62802', '+1-635-243-2015x623', '[email protected]');
INSERT INTO Companies (CompanyID, Name, Address, Phone, Email) VALUES (NULL, 'Other Company', 'Unit 5699 Box 8173 DPO AP 62802', '+1-635-243-2015x623', '[email protected]');
INSERT INTO Companies (CompanyID, Name, Address, Phone, Email) VALUES (NULL, 'Other Company', 'Unit 5699 Box 8173 DPO AP 62802', '+1-635-243-2015x623', '[email protected]');
Para esta prueba, teniendo un servidor detenido realizamos una inserción de 5 registros, la cual se replico hacia nuestro servidor que esta en linea
6.3 Levantamos el nodo faltante
En el nodo caido ejecutamos:
Levantamos nuevamente nuestro nodo y al hacerlo se nos replica la información que se agrego previamente
Levantamos nuevamente nuestro nodo y al hacerlo se nos replica la información que se agrego previamente:
select * from Companies order by CompanyID DESC LIMIT 10 \G
Extrabackup tiene una forma de conocer el ultimo hash de los registros insertados, con esto se guiá de que tan sincronizado esta con las otras bases de datos.
7. Levantar un nodo con xtrabackup y unirlo al cluster
En esta practica levantaremos un nuevo nodo con Docker y lo uniremos a nuestro cluster, para ello lo primero que debemos hacer es modificar nuestro archivo docker-compose.yml
6.1 Modificar docker-compose.yml
Agregamos un nuevo servicio llamado mysql-server-4
mysql-server-4:
build:
context: .
dockerfile: Dockerfile
container_name: mysql-server-4
hostname: node-4
networks:
custom_network:
ipv4_address: 172.20.0.6
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- mysql4_data:/var/lib/mysql
ports:
- "3311:3306"
command: bash -c "tail -f /dev/null"
Al final nuestro archivo docker-compose.yml
se vera de la siguiente manera
version: '3.8'
services:
mysql-server-1:
build:
context: .
dockerfile: Dockerfile
container_name: mysql-server-1
hostname: node-1
networks:
custom_network:
ipv4_address: 172.20.0.3
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- mysql1_data:/var/lib/mysql
ports:
- "3308:3306" # Mapeo de puerto para acceso externo
#command: mysqld_safe
command: bash -c "tail -f /dev/null"
mysql-server-2:
build:
context: .
dockerfile: Dockerfile
container_name: mysql-server-2
hostname: node-2
networks:
custom_network:
ipv4_address: 172.20.0.4
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- mysql2_data:/var/lib/mysql
ports:
- "3309:3306" # Mapeo de puerto para acceso externo
# command: mysqld_safe
command: bash -c "tail -f /dev/null"
mysql-server-3:
build:
context: .
dockerfile: Dockerfile
container_name: mysql-server-3
hostname: node-3
networks:
custom_network:
ipv4_address: 172.20.0.5
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- mysql3_data:/var/lib/mysql
ports:
- "3310:3306" # Mapeo de puerto para acceso externo
# command: mysqld_safe
command: bash -c "tail -f /dev/null"
mysql-server-4:
build:
context: .
dockerfile: Dockerfile
container_name: mysql-server-4
hostname: node-4
networks:
custom_network:
ipv4_address: 172.20.0.6
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- mysql4_data:/var/lib/mysql
ports:
- "3311:3306"
command: bash -c "tail -f /dev/null"
networks:
custom_network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
6.2 Iniciar el nuevo nodo
Para inciar nuestro nodo ejecutamos el siguiente comando
docker-compose up -d mysql-server-4
De esta manera se levantara el nuevo nodo sin afectar a los que ya tenemos, una vez que se haya inicializado sera necesario realizar la configuración correspondiente
6.3 Configurar nuevo nodo
Una vez que hayamos levantado el nuevo nodo, sera necesario identificar su ID de contenedor, para ello usamos el siguiente comando
Identificamos el contenedor por su nombre y accedemos a el
docker exec -it <id_contenedor> bash
Una vez hayamos ingresado, repetimos los puntos del paso Configuración de los nodos, con la diferencia de que al momento de modificar el archivo wsrep.cnf
, en la variable wsrep_cluster_address
agregaremos la IP de nuestro nuevo nodo, por lo que ahora se veria de la siguiente manera
wsrep_cluster_address=gcomm://172.20.0.3,172.20.0.4,172.20.0.5,172.20.0.6
Una vez hayamos realizado las configuración correspondiente guardamos los cambios realizados al archivo
6.4 Actualizar nodos
Debido a que hemos agregado un nuevo nodo, sera necesario modificar la configuración de nuestros otros nodos para poder agregarlo al cluster, por lo que sera necesario modificar el archivo wsrep.cnf
en nuestros nodos.
Primero, debemos detener mysql
A continuación, modificamos el archivo wsrep.cnf
nano /etc/mysql/percona-xtradb-cluster.conf.d/wsrep.cnf
Modificamos unicamente la variable wsrep_cluster_address
y agregamos la IP de nuestro nuevo nodo, al final nos deberia quedar de la siguiente manera
wsrep_cluster_address=gcomm://172.20.0.3,172.20.0.4,172.20.0.5,172.20.0.6
6.5 Iniciar nodos
Iniciamos nuevamente nuestros nodos, comenzando por el nodo 1, en cuyo caso lo haremos de la siguiente manera
/etc/init.d/mysql bootstrap-pxc
Para nuestros otros nodos lo haremos de la siguiente manera
Es importante iniciar los nodos uno a uno, es decir, esperara a que se inicie uno para seguir con el otro sucesivamente hasta iniciar todos nuestros nodos
6.6 Comprobación
Una vez hayamos iniciado nuestros nodos sera necesario comprobar nuevamente el estado del cluster, para ello en el nodo 1 accedemos a mysql
Ejecutamos el siguiente comando
show status like 'wsrep%';
En la salida del comando, en la variable wsrep_cluster_size
deberiamos observar que ahora dice 4, asi como la variable wsrep_incoming_addresses
en la cual ahora podremos observar que se ha añadido la IP de nuestro nuevo nodo
+----------------------------------+-----------------------------------------------------------------+
| wsrep_ist_receive_seqno_end | 0 |
| wsrep_incoming_addresses | 172.20.0.3:3306,172.20.0.4:3306,172.20.0.5:3306,172.20.0.6:3306 |
| wsrep_cluster_weight | 4 |
| wsrep_desync_count | 0 |
| wsrep_evs_delayed | |
| wsrep_evs_evict_list | |
| wsrep_evs_repl_latency | 0.000103651/0.000977444/0.00479661/0.00171043/6 |
| wsrep_evs_state | OPERATIONAL |
| wsrep_gcomm_uuid | 9f43bdb5-6975-11ef-8a50-9ab358c7ecaa |
| wsrep_gmcast_segment | 0 |
| wsrep_cluster_conf_id | 4 |
| wsrep_cluster_size | 4 |
| wsrep_cluster_state_uuid | aab1fa2a-6972-11ef-b4c4-5f1c0e026749 |
| wsrep_cluster_status | Primary |
| wsrep_connected | ON |
| wsrep_local_bf_aborts | 0 |
| wsrep_local_index | 0 |
| wsrep_provider_name | Galera |
| wsrep_provider_vendor | Codership Oy <info@codership.com> |
| wsrep_provider_version | 3.63(rf47405c) |
| wsrep_ready | ON |
+----------------------------------+-----------------------------------------------------------------+
Con esto habremos finalizado esta practica de Percona XDB Cluster con Docker.
Al finalizar, nuestro cluster quedaria de la siguiente manera
Video Tutorial
Puedes ver el paso a paso en el video de nuestro canal.
Utilidades para el Desarrollo
Debido a que esto se realiza en un entorno de Desarrollo/Pruebas para entender el concepto y funcionamiento de Percona XtradbCluster, brindaremos los siguientes comandos para facilitar la solución de errores:
Logs de Errores de Mysql Percona Cluster:
tail -f /var/log/mysqld.log
Logs de Errores de Xtrabackup (al momento de levantar un nuevo nodo)
tail -f /var/lib/mysql//innobackup.backup.log
Error al inicializar Cluster
Una cosa a tener en cuenta es que si el vagrant se detiene bruscamente (como si se apagaran los servidores) el cluster mostrara un error al volver a levantarse, ya que desconoce que servidor fue el ultimo en detenerse.
Teniendo en cuenta esto, podemos levantar el Cluster nuevamente entrando al nodo 1 (nodo principal) y modificando el siguiente archivo:
nano /var/lib/mysql/grastate.dat
Modifica la variable safe_to_bootstrap
, de la siguiente forma:
Con esto ya podremos levantar el cluster nuevamente:
/etc/init.d/mysql bootstrap-pxc
Problemas de Sincronizacion debido a Firewall
Puedes comprobar que los puertos 4444, 4567 y 4568 esten abiertos entre las maquinas virtuales de la siguiente forma:
En el servidor que se unira al cluster (JOINER):
En el servidor que sera el donante (DONOR):
a
echo "hello" | socat - TCP:ip.adr.of.donor:4444
Con esto puedes comprobar si los puertos se encuentran abiertos o tienes inconvenientes con Firewall. El servidor nuevo estará a la escucha de informacion en el puerto designado (en este caso 4444) y el servidor Donante, enviara un "hello" que se imprimira en el donante.
Levantar cluster con un Backup usando Xtrabackup
Debido a que Percona Cluster necesita una tabla en donde almacenar datos de la replicacion y el cluster, se necesita realizar lo siguiente en el nodo que iniciará el cluster. Con el MySQL funcionando ejecuta en la terminal de ubuntu:
Esto deberia mostrar un output parecido a esto:
bd.table1 OK
bd.table2 OK
bd.table OK
...
sys.sys_config OK
Upgrade process completed successfully.
Checking if update is needed.
Puedes comprobar que el cambio funcionío ejecutando lo siguiente:
SHOW GLOBAL VARIABLES LIKE 'wsrep_sync_wait';
Saber si el cluster esta en funcionamiento
Puedes ejecutar la siguiente query:
show global status where variable_name IN ('wsrep_local_state','wsrep_local_state_comment','wsrep_local_commits','wsrep_received','wsrep_cluster_size','wsrep_cluster_status','wsrep_connected','wsrep_ready');
Esto brindará un output como el siguiente:
+---------------------------+---------+
| Variable_name | Value |
+---------------------------+---------+
| wsrep_received | 7 |
| wsrep_local_commits | 0 |
| wsrep_local_state | 4 |
| wsrep_local_state_comment | Synced |
| wsrep_cluster_size | 3 |
| wsrep_cluster_status | Primary |
| wsrep_connected | ON |
| wsrep_ready | ON |
+---------------------------+---------+
8 rows in set (0.00 sec)
Explicacion de cada parametro:
- wsrep_received: Esta variable indica cuántos eventos de replicación (transacciones) ha recibido el nodo desde los otros nodos del clúster. En este caso, el nodo ha recibido 7 eventos.
- wsrep_local_commits: Muestra cuántas transacciones locales ha confirmado el nodo en su propia base de datos. En este caso, el nodo no ha hecho ninguna confirmación de transacciones propias, por eso está en 0.
- wsrep_local_state: Indica el estado del nodo dentro del clúster. El valor 4 corresponde al estado Synced, lo que significa que el nodo está completamente sincronizado y listo para procesar transacciones.
- wsrep_local_state_comment: Es un comentario en texto del estado del nodo. Como el valor es Synced, confirma que el nodo está sincronizado con el resto del clúster. Mas Info
- wsrep_cluster_size: Indica el número de nodos activos en el clúster. En este caso, hay 3 nodos activos.
- wsrep_cluster_status: Muestra el estado del clúster. Primary significa que el clúster está operativo y que los nodos pueden comunicarse y replicar datos correctamente. Este es el estado deseado
- wsrep_connected: Indica si el nodo está conectado al clúster. ON significa que el nodo está conectado correctamente a los otros nodos.