Crear un cluster de base de datos MariaDB con Galera
MariaDB es un sistema de gestión de bases de datos derivado de MySQL con licencia GPL (General Public License). Es desarrollado por Michael (Monty) Widenius (fundador de MySQL), la fundación MariaDB y la comunidad de desarrolladores de software libre.[1]
Por otro lado Galera es un sistema de cluster síncrono y multi-maestro para MariaDB. [2]
Esta guía es parte de un conjunto de tutoriales para bases de datos con MariaDB y mostrará la manera más básica para desplegar un cluster multi-maestro con MariaDB Galera Cluster.
Guías |
---|
Crear un cluster de base de datos MariaDB con Galera |
Configurar balanceador de cargas para MariaDB Galera Cluster |
Contenido
Prerrequisitos
Servidores
Se requiere de al menos 3 nodos para desplegar el cluster, ya sea físicos o virtuales.
Las características de cada uno dependerá del contexto en donde se vaya a desplegar el cluster.
Se recomienda al menos 4 cores y 8 GB de RAM
Software
Esta guía esta planteada para ser ejecutada en el sistema Debian GNU/Linux 10, no obstantes muchos de los pasos pueden ser replicados en otras distribuciones de GNU/Linux.
Se asume que el sistema operativo ya se encuentra instalado, que los equipos cuentan con conectividad de red y pueden comunicarse entre ellos.
Asimismo, es necesario que cada equipo pueda resolver el nombre de los otros por lo que se debe editar el archivo /etc/hosts
y agregar cada nodo:
127.0.0.1 localhost 172.16.0.34 db00.beta.ucr.ac.cr db00 172.16.0.35 db01.beta.ucr.ac.cr db01 172.16.0.36 db02.beta.ucr.ac.cr db02
Instalación
MariaDB Galera Cluster
Los siguientes comandos agregan el repositorio oficial de MariaDB e instalan el software requerido.
Para determinar cuál repositorio debe ser configurado, puede consultarse el sitio https://downloads.mariadb.org/mariadb/repositories/
sudo apt-get install software-properties-common dirmngr sudo apt-key adv --fetch-keys 'https://mariadb.org/mariadb_release_signing_key.asc' sudo add-apt-repository 'deb [arch=amd64] http://nyc2.mirrors.digitalocean.com/mariadb/repo/10.4/debian buster main' sudo apt-get update sudo apt-get install mariadb-server
La secuencia de comandos anterior debe ejecutarse en los 3 nodos.
Configuración
Archivo de configuración
En todos los nodos, se edita o se crea el archivo /etc/mysql/mariadb.conf.d/galera.cnf
sudo editor /etc/mysql/mariadb.conf.d/galera.cnf
Se agrega el siguiente contenido
[mysqld] binlog_format=ROW default-storage-engine=innodb innodb_autoinc_lock_mode=2 bind-address=0.0.0.0 # Galera Provider Configuration wsrep_on=ON wsrep_provider=/usr/lib/galera/libgalera_smm.so # Galera Cluster Configuration wsrep_cluster_name="db_cluster_beta" wsrep_cluster_address="gcomm://db00,db01,db02" # Galera Synchronization Configuration wsrep_sst_method=rsync # Can use mariabackup: apt install mariadb-backup # https://mariadb.com/kb/en/library/mariadb-backup-overview/#using-mariadb-backup-for-galera-ssts #wsrep_sst_method=mariabackup #wsrep_sst_auth=USER:PASSWORD
# Galera Node Configuration wsrep_node_address="IP_DEL_NODO" wsrep_node_name="NOMBRE_DEL_NODO"
Nótese que wsrep_node_address y wsrep_node_name deben coincidir con la dirección IP y el nombre del nodo en donde se está creando el archivo. Así, por ejemplo, en el nodo db0 estas variables serán "172.16.0.34" y "db0" respectivamente.
Construcción del cluster
Opcionalmente, para asegurar la instalación de MariaDB y borrar las bases de datos de pruebas se ejecuta el siguiente comando solamente en uno de los nodos
sudo mysql_secure_installation
Se detiene el servicio de MariaDB en todos los nodos ejecutando el siguiente comando en cada uno de ellos
sudo systemctl stop mysql
Se verifica que el servicio esté detenido
sudo systemctl is-active mysql
El comando debe mostrar "inactive"
Ahora, en el nodo db00 se crea el nuevo cluster de Galera ejecutando el siguiente comando solamente en el nodo db00
sudo galera_new_cluster
Se verifica que el cluster haya inicializado
mysql -u root -p -e "SHOW STATUS LIKE 'wsrep_cluster_size'"
Debe mostrar lo siguiente
+--------------------+-------+ | Variable_name | Value | +--------------------+-------+ | wsrep_cluster_size | 1 | +--------------------+-------+
Luego, se inicia el servicio de MariaDB normalmente en los otros nodos
sudo systemctl start mysql
Se verifica que los nodos hayan sido agregados al cluster
mysql -u root -p -e "SHOW STATUS LIKE 'wsrep_cluster_size'"
Ahora debe mostrarse el número total de nodos
+--------------------+-------+ | Variable_name | Value | +--------------------+-------+ | wsrep_cluster_size | 3 | +--------------------+-------+
Por último, se requiere copiar la información de la cuenta de mantenimiento de Debian en los otros nodos del cluster. Para esto se copia la información del archivo
/etc/mysql/debian.cnf
del nodo db00 a los otros nodos. Puede realizarse de manera manual o utilizando el comando scp.
NOTA: Se debe recordar que la replicación de Galera solo funciona sobre bases de datos en InnoDB. Por ejemplo, base de datos de system como 'mysql' (MyISAM) no son replicadas, excepto en la replicación inicial; no obstante, sentencias como CREATE USER y GRANT sí se replican, por lo que la creación de un usuario con estas sentencias sí se replicarán en el cluster pero si se utiliza INSERT no.
Pruebas de replicación
Se crea la base de datos playground en el nodo db00:
(db00)$ mysql -u root -p -e 'CREATE DATABASE playground; CREATE TABLE playground.equipment ( id INT NOT NULL AUTO_INCREMENT, type VARCHAR(50), quant INT, color VARCHAR(25), PRIMARY KEY(id)); INSERT INTO playground.equipment (type, quant, color) VALUES ("slide", 2, "blue");'
Se observa el cambio en el nodo db01:
(db01)$ mysql -u root -p -e 'SELECT * FROM playground.equipment;'
Se mostrarán la tabla y el valor insertados desde nodo db00.
Luego, se inserta un nuevo valor desde nodo db01
(db01)$ mysql -u root -p -e 'INSERT INTO playground.equipment (type, quant, color) VALUES ("swing", 10, "yellow");'
Se observa el cambio en nodo db02:
(db02)$ mysql -u root -p -e 'SELECT * FROM playground.equipment;'
Se mostrarán los valores del nodo db00 y db01.
Se inserta un nuevo valor desde nodo db02
(db02)$ mysql -u root -p -e 'INSERT INTO playground.equipment (type, quant, color) VALUES ("seesaw", 3, "green");'
Se puede observar que los cambios se reflejan en todos los nodos.
Problemas
Nodos no se comunican
Se debe verificar que los puertos del firewall estén abiertos. Galera puede hacer uso de 4 puertos:
- 3306 For MySQL client connections and State Snapshot Transfer that use the mysqldump method.
- 4567 For Galera Cluster replication traffic, multicast replication uses both UDP transport and TCP on this port.
- 4568 For Incremental State Transfer.
- 4444 For all other State Snapshot Transfer.
Recuperar nodos luego de un fallo
Si se da un fallo en todo el cluster y debe ser reiniciado (ej. un fallo eléctrico), el servicio no iniciará normalmente y se debe realizar un proceso de recuperación. En las bitácoras el mensaje de error sería similar a este:
mysqld[1411]: 2018-06-26 15:16:52 0 [ERROR] WSREP: failed to open gcomm backend connection: 110: failed to reach primary view: 110 (Connection timed out) mysqld[1411]: at gcomm/src/pc.cpp:connect():158 mysqld[1411]: 2018-06-26 15:16:52 0 [ERROR] WSREP: gcs/src/gcs_core.cpp:gcs_core_open():208: Failed to open backend connection: -110 (Connection timed out) mysqld[1411]: 2018-06-26 15:16:52 0 [ERROR] WSREP: gcs/src/gcs.cpp:gcs_open():1458: Failed to open channel 'db_cluster_beta' at 'gcomm://db00,db01,db02': -110 (Connection timed out) mysqld[1411]: 2018-06-26 15:16:52 0 [ERROR] WSREP: gcs connect failed: Connection timed out mysqld[1411]: 2018-06-26 15:16:52 0 [ERROR] WSREP: wsrep::connect(gcomm://db00,db01,db02) failed: 7 mysqld[1411]: 2018-06-26 15:16:52 0 [ERROR] Aborting systemd[1]: mariadb.service: Main process exited, code=exited, status=1/FAILURE systemd[1]: Failed to start MariaDB 10.3.7 database server.
El primer paso es determinar el seqno
(Número de secuencia) válido, esto determina cuál de los nodos posee el último estado consistente.
Se debe revisar el archivo /var/lib/mysql/grastate.dat
(la ubicación puede ser diferente según la distribución) en cada uno de los nodos. El nodo con el seqno
más grande es el que posee los datos más actuales antes de la caída.
El siguiente es un ejemplo del archivo grastate.dat
# GALERA saved state version: 2.1 uuid: cf9e1fb2-7660-11e8-9b5b-9fe6692e98e3 seqno: -1 safe_to_bootstrap: 1
Si el archivo muestra en seqno
en -1, significa que el nodo no se apagó correctamente. Para determinar el seqno
se ejecuta el siguiente comando:
mysqld --wsrep-recover
Esto iniciará mysqld, leerá los encabezados de InnoDB y luego se apagará. La última posición de wsrep se mostrará en las bitácoras o en pantalla. Es importante determinar el seqno
de todos los nodos que tienen un uuid
válido en el archivo grastate.dat
.
[Note] WSREP: Recovered position: cf9e1fb2-7660-11e8-9b5b-9fe6692e98e3:165060
En el caso anterior, el seqno
es 165060, este valor puede ser introducido manualmente en el archivo grastate.dat
. Se debe revisar cada uno de los nodos para determinar cuál posee el número de secuencia más grande.
Además del número de secuencia, el archivo muestra la opción safe_to_bootstrap
que, cuando posee el valor de 1, podría ayudar a determinar cuál nodo puede ser utilizado para iniciar el cluster. Si fuera el caso que ninguno de los nodos posee safe_to_bootstrap: 1
, se debe determinar el número de secuencia y luego cambiar el valor de 0 a 1 para el nodo más apto y así forzarlo como nodo de inicialización.
Una vez determinado el nodo más apto para iniciar el cluster, se ejecuta el siguiente comando solamente en dicho nodo y se espera a que la base de datos inicie:
mysqld_safe -- wsrep_cluster_address=gcomm:// &;
Luego de que se tiene la base de datos arriba, se inicia el servicio de MariaDB en los demás nodos como normalmente se haría, solo uno a la vez:
systemctl start mariadb
Una ves que todos los nodos están arriba y en estado consistente (primary state), se reinicia el primer nodo (el que fue ejecutado con mysqld_safe
) de la manera normal para que de esta forma se reincorpore al cluster como un nodo más y no como el iniciador.
Mejoras de rendimiento
Las mejoras de rendimiento (performace) deben analizarse según la carga de cada sistema, el rendimiento de los servidores de base de datos, discos duros y red.
Se recomienda el uso de herramientas para medir el rendimiento y otras que sugieren recomendaciones como mysqltuner y PHPMyAdmin.
Algunos valores que se pueden tomar de referencia y que fueron utilizados en los servidores de prueba para la elaboración de esta guía son los siguientes:
# FILE: /etc/mysql/mariadb.conf.d/galera_performance.cnf [mysqld] # Variables innodb_flush_log_at_trx_commit=0 #innodb_doublewrite=0 #sync_binlog=0 ## Constant innodb_buffer_pool_size=5G innodb_buffer_pool_instances=5 #innodb_log_file_size=1500M #innodb_log_files_in_group=2 #innodb_locks_unsafe_for_binlog=1 #wsrep_slave_threads=32 #max_connections=1000 ##idle_readonly_transaction_timeout 0 ##idle_transaction_timeout 0 ##idle_write_transaction_timeout 0 #innodb_open_files=2000 #max_heap_table_size=1073741824 query_cache_limit=2M query_cache_size=512M #slow_query_log=ON #slow_query_log_file=/var/log/mysql/mariadb-slow.log #table_open_cache=2000 tmp_table_size=1G max-heap-table-size = 1G
Los servidores (virtuales) de la prueba poseen 4 procesadores y 16 GB de RAM, sin discos rápidos ni optimizaciones de hardware. Los valores anteriores no deben se aplicados sin primero analizar la plataforma pues son muy dependientes de los factores del contexto donde se despliega la base de datos, las consultas y los datos mismos. Para consultar los valores de las variables, visitar: https://mariadb.com/kb/en/library/server-system-variables/
La herramienta que se utilizó para realizar el benchmark fue sysbench, con el siguiente script de bash y utilizando contenedores de Docker:
#!/bin/bash # Run this manually to prepare some tables: # mysqladmin -uroot -p create sbtest # docker run -it --rm severalnines/sysbench sysbench \ # --db-driver=mysql --mysql-host=172.16.251.34 \ # --mysql-user=sbtest --mysql-password="SECURE_PASSWORD" \ # --mysql-table-engine=InnoDB --mysql-engine-trx=yes \ # --oltp-table-size=2000000 --oltp-auto-inc=off \ # --max-requests=0 --threads=1 --oltp-tables-count=10 \ # /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua prepare # The above creates a dataset roughly # 189,8*2000000*10/1024/1024 = 3620M = 3,5G DBDIR=$(dirname "$0") #NUM_THREADS="1" NUM_THREADS="1 2 4 8 16 32 64 128 256 512 1023" #TEST_DBS="172.16.251.40" # For testing maxscale LB TEST_DBS="172.16.251.34,172.16.251.35,172.16.251.36" PASS_DB="SECURE_PASSWORD" USER_DB="sbtest" for N in $NUM_THREADS; do # --oltp-auto-inc=off is undocumented, but important when running galera. # sysbench assumes that autoinc columns will be a continuos sequence 1,2,3... # but with galera they're not (auto_increment_increment) docker run -it --rm severalnines/sysbench sysbench \ --db-driver=mysql --mysql-host=$TEST_DBS \ --mysql-user=$USER_DB --mysql-password=$PASS_DB \ --mysql-table-engine=InnoDB --mysql-engine-trx=yes \ --oltp-table-size=2000000 --time=60 \ --max-requests=0 --threads=$N --oltp-tables-count=10 \ --oltp-auto-inc=off /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua run done
Enlaces
Enlaces de referencia
- https://www.digitalocean.com/community/tutorials/how-to-configure-a-galera-cluster-with-mariadb-10-1-on-ubuntu-16-04-servers
- https://linoxide.com/cluster/configure-mariadb-maxscale-galera-cluster/
- http://galeracluster.com/documentation-webpages/testingcluster.html
- https://dba.stackexchange.com/questions/157500/how-to-recover-mariadb-galera-cluster-after-full-crash
- http://galeracluster.com/documentation-webpages/restartingcluster.html
- http://openlife.cc/blogs/2011/august/running-sysbench-tests-against-galera-cluster
- https://severalnines.com/blog/benchmark-load-balancers-mysqlmariadb-galera-cluster
- http://galeracluster.com/documentation-webpages/performance.html
- https://www.slideshare.net/Severalnines/9-devopstipsforgoingintoprodwithgalera-1
- https://opensourceforu.com/2017/05/get-best-mariadb-performance-tuning/
- https://mariadb.com/kb/en/library/recommended-settings-for-benchmarks/