MariaDB 数据库是 MySQL 的一个分支,主要由开源社区维护,采用 GPL 授权许可 MariaDB 的目的是完全兼容 MySQL,包括 API 和命令行,使之能轻松成为 MySQL 的代替品。在存储引擎方面,使用 XtraDB 来代替 MySQL 的 InnoDB。
MySQL 数据库集群的相关分析,可以参考如下文章:
系统架构与设计(2)- 如何设计高并发系统的数据库架构 (一)
系统架构与设计(3)- 如何设计高并发系统的数据库架构 (二)
系统架构与设计(4)- 如何设计高并发系统的数据库架构 (三)
1. 部署环境
IP 地址(本地测试环境):192.168.0.10
操作系统:Linux CentOS 7.9
Docker 版本: 20.10.7
Docker Compose 版本: 2.6.1
MariaDB 集群目录:/home/docker/mysql_cluster
2. 创建 docker-compose.yml
$ cd /home/docker/mysql_cluster
$ vim docker-compose.yml
version: "3" services: mariadb_master: image: mariadb:10.4 container_name: mariadb_master-10.4 ports: - "3306:3306" restart: always environment: - MARIADB_ROOT_PASSWORD=123456 volumes: - /home/docker/mysql_cluster/master/conf:/etc/mysql/conf.d - /home/docker/mysql_cluster/master/data:/var/lib/mysql - /home/docker/mysql_cluster/master/log:/var/log/mysql mariadb_node_1: image: mariadb:10.4 container_name: mariadb_node_1-10.4 ports: - "3307:3307" restart: always environment: - MARIADB_ROOT_PASSWORD=123456 volumes: - /home/docker/mysql_cluster/node_1/conf:/etc/mysql/conf.d - /home/docker/mysql_cluster/node_1/data:/var/lib/mysql - /home/docker/mysql_cluster/node_1/log:/var/log/mysql mariadb_node_2: image: mariadb:10.4 container_name: mariadb_node_2-10.4 ports: - "3308:3308" restart: always environment: - MARIADB_ROOT_PASSWORD=123456 volumes: - /home/docker/mysql_cluster/node_2/conf:/etc/mysql/conf.d - /home/docker/mysql_cluster/node_2/data:/var/lib/mysql - /home/docker/mysql_cluster/node_2/log:/var/log/mysql
3. 配置文件
1) 创建 master 的 my_mariadb.conf 文件
在 /home/docker/mysql_cluster/master/conf 目录下,创建 my_mariadb.conf 文件,内容如下:
[mysqld] server-id=1 port=3306 #basedir=/usr/local/mysql #tmpdir=/tmp datadir=/var/lib/mysql # 查询日志,默认在 /var/lib/mysql 目录下 #general_log=1 #general_log_file=mysql_general-1.log # 二进制日志,默认在 /var/lib/mysql 目录下 log_bin=mysql_binlog-1 # 慢查询日志,默认在 /var/log/mysql 目录下 #slow_query_log=1 #long_query_time=1 #slow_query_log_file=mysql_slow_query-1.log # 错误日志,指定到 /var/log/mysql 目录 log_error=/var/log/mysql/mysql_err-1.log
注:MariaDB (MySQL) 的默认配置文件是 /etc/mysql/my.cnf 文件。如果想要自定义配置,在 /etc/mysql/conf.d 目录中创建 *.cnf 文件。新建的文件可以任意起名,只要保证后缀名是 cnf 即可。新建的文件中的配置项可以覆盖 /etc/mysql/my.cnf 中的配置项。
2) 创建 node_1 的 my_mariadb.conf 文件
在 /home/docker/mysql_cluster/node_1/conf 目录下,创建 my_mariadb.conf 文件,内容如下:
[mysqld] server-id=2 port=3307 #basedir=/usr/local/mysql #tmpdir=/tmp datadir=/var/lib/mysql # 查询日志,默认在 /var/lib/mysql 目录下 #general_log=1 #general_log_file=mysql_general-2.log # 二进制日志,默认在 /var/lib/mysql 目录下 #log_bin=mysql_binlog-2 # 慢查询日志,默认在 /var/log/mysql 目录下 #slow_query_log=1 #long_query_time=1 #slow_query_log_file=mysql_slow_query-2.log # 错误日志,指定到 /var/log/mysql 目录 log_error=/var/log/mysql/mysql_err-2.log # relay-log relay-log=mysql-relaylog-2
3) 创建 node_2 的 my_mariadb.conf 文件
在 /home/docker/mysql_cluster/node_2/conf 目录下,创建 my_mariadb.conf 文件,内容如下:
[mysqld] server-id=3 port=3308 #basedir=/usr/local/mysql #tmpdir=/tmp datadir=/var/lib/mysql # 查询日志,默认在 /var/lib/mysql 目录下 #general_log=1 #general_log_file=mysql_general-3.log # 二进制日志,默认在 /var/lib/mysql 目录下 #log_bin=mysql_binlog-3 # 慢查询日志,默认在 /var/log/mysql 目录下 #slow_query_log=1 #long_query_time=1 #slow_query_log_file=mysql_slow_query-3.log # 错误日志,指定到 /var/log/mysql 目录 log_error=/var/log/mysql/mysql_err-3.log # relay-log relay-log=mysql-relaylog-3
4. 启动
$ cd /home/docker/mysql_cluster # 进入 docker-compose.yml 所在目录
$ docker-compose up -d # 在后台运行
[+] Running 4/4 ⠿ Network mysql_cluster_default Created 0.0s ⠿ Container mariadb_node_2-10.4 Started 0.6s ⠿ Container mariadb_master-10.4 Started 0.6s ⠿ Container mariadb_node_1-10.4 Started 0.7s
注:本地 docker 没有所需要的镜像时,会自动下载所需的镜像。遇到无法自动下载的情况,可以使用 docker pull 命令下载所需的镜像,再运行 docker-compose up 命令。
$ docker images # 查看镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
mariadb 10.4 801fdf0164b2 2 weeks ago 404MB
$ docker-compose ps # 类似 docker ps 的作用
NAME COMMAND SERVICE STATUS PORTS mariadb_master-10.4 ... mariadb_master running 0.0.0.0:3306->3306/tcp,... mariadb_node_1-10.4 mariadb_node_1 running 0.0.0.0:3307->3307/tcp,... mariadb_node_2-10.4 mariadb_node_2 running 0.0.0.0:3308->3308/tcp,...
容器内的程序要在挂载的 log 目录下创建 log 文件,需要确保 root/root 以外的用户也有 log 目录的写权限,修改 log 目录的权限,命令如下:
$ chmod a+w /home/docker/mysql_cluster/master/log /home/docker/mysql_cluster/node_1/log /home/docker/mysql_cluster/node_2/log
修改后需要重启容器,命令如下:
$ docker restart mariadb_master-10.4 mariadb_node_1-10.4 mariadb_node_2-10.4
5. 配置主从复制
1) master 配置
$ docker exec -it mariadb_master-10.4 /bin/bash # 进入 master 容器
# 进入容器后,使用 ip addr 命令查看容器内 IP 地址 root@986cfd3cdf63:/# ip addr ... 124: eth0@if125: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:19:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.25.0.4/16 brd 172.25.255.255 scope global eth0 valid_lft forever preferred_lft forever 注:这里容器内 IP 地址为 172.25.0.4 # 进入 MySQL 命令行控制台 root@986cfd3cdf63:/# mysql -u root -p Enter password: Welcome to the MariaDB monitor. Commands end with ; or \g. ... # 运行以下 MariaDB 命令,查看 log-bin 的开启状态,ON 表示开启,OFF 表示关闭 MariaDB [(none)]> show variables where variable_name like 'log_bin'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | log_bin | ON | +---------------+-------+ 1 row in set (0.001 sec)` # 创建数据库用户 MariaDB [(none)]> grant replication slave on *.* to 'node_copy'@'%' identified by '123456'; Query OK, 0 rows affected (0.002 sec) MariaDB [(none)]> show grants for 'node_copy'; +--------------------------------------------------------------+ | Grants for node_copy@% | +--------------------------------------------------------------+ | GRANT REPLICATION SLAVE ON *.* TO `node_copy`@`%` ... +--------------------------------------------------------------+ 1 row in set (0.000 sec) # 查看主机状态 MariaDB [(none)]> show master status; +-----------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +-----------------------+----------+--------------+------------------+ | mysql_binlog-1.000001 | 333 | | | +-----------------------+----------+--------------+------------------+ 1 row in set (0.000 sec)
注:做主从复制前,最好将主数据库进行备份。
2) node_1 配置
$ docker exec -it mariadb_node_1-10.4 /bin/bash # 进入 node_1 容器
# 进入 MySQL 命令行控制台 root@59cf938b5a35:/# mysql -P 3307 -u root -p Enter password: Welcome to the MariaDB monitor. Commands end with ; or \g. ... MariaDB [(none)]> stop slave; Query OK, 0 rows affected (0.006 sec) # 运行如下命令连接到 master MariaDB [(none)]> change master to master_host='172.25.0.4',master_port=3306, -> master_user='node_copy',master_password='123456', -> master_log_file='mysql_binlog-1.000001', master_log_pos=333; 参数说明: master_host:主数据库的 IP 地址; master_port:主数据库的运行端口; master_user:在主数据库创建的用于同步数据的用户账号; master_password:在主数据库创建的用于同步数据的用户密码; master_log_file:指定从数据库要复制数据的日志文件,通过查看主数据的状态,获取 File 参数; master_log_pos:指定从数据库从哪个位置开始复制数据,通过查看主数据的状态,获取Position 参数; master_connect_retry:连接失败重试的时间间隔,单位为秒。 注:如果 change master 不成功,可以尝试运行 reset slave; 后再试。 master_host、master_log_file 和 master_log_pos,在运行 docker-compose down 命令后,再运行 docker-compose up 命令, 会发生变化,需要重新配置。 MariaDB [(none)]> start slave; Query OK, 0 rows affected (0.001 sec) MariaDB [(none)]> show slave status \G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 172.25.0.4 Master_User: node_copy Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql_binlog-1.000001 Read_Master_Log_Pos: 672 Relay_Log_File: mysql-relaylog-2.000001 Relay_Log_Pos: 707 Relay_Master_Log_File: mysql_binlog-1.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes ... 1 row in set (0.000 sec) 注:Slave_IO_Running 和 Slave_SQL_Running 都是 Yes,表示 node_1 已经连接上 Master。
3) node_2 配置
$ docker exec -it mariadb_node_2-10.4 /bin/bash # 进入 node_2 容器
# 进入 MySQL 命令行控制台 root@43302d136143:/# mysql -P 3308 -u root -p Enter password: Welcome to the MariaDB monitor. Commands end with ; or \g. ... MariaDB [(none)]> stop slave; Query OK, 0 rows affected (0.006 sec) # 运行如下命令连接到 master MariaDB [(none)]> change master to master_host='172.25.0.4', master_port=3306, -> master_user='node_copy', master_password='123456', -> master_log_file='mysql_binlog-1.000001', master_log_pos=333; 参数说明: master_host:主数据库的 IP 地址; master_port:主数据库的运行端口; master_user:在主数据库创建的用于同步数据的用户账号; master_password:在主数据库创建的用于同步数据的用户密码; master_log_file:指定从数据库要复制数据的日志文件,通过查看主数据的状态,获取 File 参数; master_log_pos:指定从数据库从哪个位置开始复制数据,通过查看主数据的状态,获取Position 参数; master_connect_retry:连接失败重试的时间间隔,单位为秒。 注:如果 change master 不成功,可以尝试运行 reset slave; 后再试。 master_host、master_log_file 和 master_log_pos,在运行 docker-compose down 命令后,再运行 docker-compose up 命令, 会发生变化,需要重新配置。 MariaDB [(none)]> start slave; Query OK, 0 rows affected (0.001 sec) MariaDB [(none)]> show slave status \G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 172.25.0.4 Master_User: node_copy Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql_binlog-1.000001 Read_Master_Log_Pos: 333 Relay_Log_File: mysql-relaylog-3.000002 Relay_Log_Pos: 560 Relay_Master_Log_File: mysql_binlog-1.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes ... 1 row in set (0.000 sec) 注:Slave_IO_Running 和 Slave_SQL_Running 都是 Yes,表示 node_2 已经连接上 Master。
$ docker exec -it mariadb_node_2-10.4 /bin/bash # 进入 node_1 容器
4) 测试
在 master 的 MariaDB 命令行下,运行如下命令:
MariaDB [(none)]> CREATE DATABASE IF NOT EXISTS testdb; Query OK, 1 row affected (0.000 sec) MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | testdb | +--------------------+ 4 rows in set (0.001 sec)
在 node_1 的 MariaDB 命令行下,运行如下命令:
MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | testdb | +--------------------+ 4 rows in set (0.000 sec)
在 node_2 的 MariaDB 命令行下,运行如下命令:
MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | testdb | +--------------------+ 4 rows in set (0.000 sec)
测试成功,node_1 和 node_2 上都出现了 testdb 数据库。
5) 命令说明
show master status; # 查看 master 的状态,当前的日志及位置
show slave status; # 查看 slave 的状态.
reset slave; # 重置 slave 状态,用于删除 slave 数据库的 relaylog 日志文件,并重新启用新的 relay-log 文件。并会重置主从关系,删除 master.info 文件和 relay-log.info 文件
start slave; # 启动 slave 状态 (开始监听 msater 的变化)
stop slave; # 停止 slave 状态;
set global sql_slave_skip_counter = n # 跳过导致复制终止的n个事件,仅在 slave 线程没运行的状况下使用