这里我要做的是MariaDB主从复制+MaxScale读写分离集群和自动化故障转移。
环境:

  • 操作系统: CentOS 8.1
  • 数据库: mariadb 10.3.17
  • 数据库代理: maxscale 2.4.6

需要注意, maxscale软件并不存在CentOS8默认源中,需要到MariaDB官网自行下载安装。为方便国内环境下载,这里我将MaxScale整合到我自建的repo库中了CentOS-Extension.repo。配置好repo后,就可以直接使用命令yum install maxscale安装即可。
注:MaxScale使用的BSL协议,属于商用协议,如需商用,并且使用数量超过2台,则需要购买授权。
在 2024-01-15后,MaxScale 2.4.6将从BSL协议转变为GPL 2.0协议。

注意,我这里将MaxScale和主MariaDB服务器放在同一台服务器上了,在配置时需要留意!!

大致的网络结构如下图:
集群网络架构图

个人难免会有错误或有疏漏的地方,还望指出,详细的还是以MariaDB 官方教程为准。

MariaDB主从集群搭建

MariaDB主从复制是通过二进制日志文件实现,在主服务器上完成所有的写入操作,通过二进制日志文件,将数据库改动发送给从服务器。从服务器接受到的二进制日志文件,会转储为relay log(中继日志),然会再在数据库中重建。
同时需要注意,主从复制集群具有单向性,在从服务器进行的任何写入操作将不会同步至主服务器上。这个问题将通过 MaxScale 的读写分离模块来解决。
还有一个不在本文范围的问题,当有多太主服务器时,将会涉及到数据同步问题,很多公司耗费了大量的人力物力都没法完全解决的文件,MariaDB 支持Galera 集群,这是一个高可用的解决方案,虽然降低了服务器新能,但是保证数据的一致性,可以用在读取性能要求大于写入性能的地方。

主服务器配置

首先是配置主服务器(10.0.0.101)的配置文件:

# file: /etc/my.cnf.d/mariadb-server.cnf

……
[mysqld]
……
log-bin=bin-log    #指定二进制日志文件名称,同时会开启二进制日志文件
# 默认MariaDB使用的是混合二进制日志文件,也就是命令和二进制的数据库改动将都将记录到二进制日志中
log-bin-index=bin-log.index    # 指定二进制日志文件的索引位置
#注意,以上两个配置指定的文件路径都是基于 datadir 配置的
server-id=100    #指定全局唯一服务器ID,ID 可以为 1~65536 的任意一个。
port=63132    #指定服务器的监听端口
# 这里我会将MaxScale配置监听在3306端口上,所以需要修改MariaDB的默认监听端口
# 如果开启了SELinux,需要配置监听在规定的特殊端口上,如果没有则忽略。
# SELinux规定的监听端口为:1186,3306,63132-63164
……

启动主服务器

systemctl start mariadb
# 开启防火墙
firewall-cmd --add-port=63132/tcp --permanent
firewall-cmd --reload

进入MariaDB 客户端,添加一个用户用于从服务器同步。

GRANT REPLICATION SLAVE ON *.* TO 'slaver'@'10.0.0.%' IDENTIFIED BY '123456';

MariaDB服务器默认就是以主服务器模式运行的,所以无需进行额外的配置即可时用。

从服务器配置

首先配置从服务器(10.0.0.102,10.0.0.103)的配置文件:

# file: /etc/my.cnf.d/mariadb-server.cnf

……
[mysqld]
……
server-id=200       # 注意,服务器ID必须为全局唯一
# 另一台从服务器的ID可以设置为201
relay-log=relay-log
# 配置将中继日志文件转储至relay-log中
# 可以不选择配置中继日志,当服务器已从模式运行时,将会自动开启中级日志功能。
relay-log-index=relay-log.index
# 指定 relay 日志的索引文件。
read-only=ON
#指定从服务器默认为只读模式,禁止任何写入操作。

启动从服务器

systemctl start mariadb
# 配置防火墙
firewall-cmd --add-service=mysql --permanent
firewall-cmd --reload

配置将主服务器指向 10.0.0.101:

CHANGE MASTER TO MASTER_HOST='10.0.0.101', MASTER_PORT=63132 ,MASTER_USER='slaver', MASTER_PASSWORD='123456';
# 注意一定不要设置Master_Log_File,当主服务器切换记录二进制日志文件时,从服务器将无法切换到对应的文件。留空将会自动进行配置。
START SLAVE;    # 启动从服务器

那么这样 MariaDB 主从复制集群就制作完成了,下面进行状态检测。

状态检测

在从服务器输入如下指令。

SHOW SLAVE STATUS\G    # 查询从节点状态信息

show slave statusG
其他一些可能会用到的命令

FLUSH LOGS;    #重新记录日志,将停止记录当前日志,开始将日志写入下一个日志。
STOP SLAVE;    # 停止从服务器
RESET SLAVE;   # 重置从服务器配置
RESET MASTER;    # 重置主服务器配置
SHOW BINARY LOGS; # 显示二进制日志文件状态
SHOW MASTER STATUS; # 显示主服务器状态

MaxScale 服务配置

MaxScale 是由MariaDB团队开发的一个软件,用于优化集群访问设计的中间件,其支持读写分离、主服务器故障转移功能,将在以下部分讲解。
注:MaxScale需要MariaDB至少 10.3.1 以上版本的支持,版本过低可能导致部分功能无法使用。

在配置MaxScale之前,需要了解部分MaxScale的工作机制:

  1. 客户端的用户认证:
    MaxScale 默认使用 MariaDB 中的 mysql.user 表进行用户认证,也就是所如果客户端想要链接到MariaDB集群,至少需要两段认证,如下图:
    如果觉得麻烦,可以直接使用通配符(%)允许所有网络的IP进行访问即可。
    MaxScale同时支持 gssapi 和 PAM 认证,这里就不过多赘述了。

  1. MaxScale拥有一套其自己的监控机制,用于监控MariaDB服务器是否存活,以及MariaDB集群的主从关系,此功能也需要拥有对应的权限。
  2. MaxScale 的工作过程:
    一、客户端请求: Client -请求-> MaxScale服务(MaxScale内部 Listener(监听器) -> Router(路由器) -> Backend Server(后端服务器))
    二、MaxScale监控:MaxScale服务(Monitor(监听器) -> Backend Server(后端服务器))

MaxScale 读写分离配置

在配置MaxScale之前,先添加几个MariaDB用户,用于 MaxScale 的使用。

CREATE USER 'maxscale'@'10.0.0.%' IDENTIFIED BY '123456';    # 创建用于用户认证的用户
GRANT SELECT ON `mysql`.* TO 'maxscale'@'10.0.0.%';    # 授权对mysql 数据库的SELECT权限
# 用于读取MySQL的用户信息
GRANT SHOW DATABASES ON *.* TO 'maxscale'@'10.0.0.%';    # 授予 SHOW DATABASES 权限

CREATE USER 'maxscale_mon'@'10.0.0.%' IDENTIFIED BY '123456';    # 创建用于服务监控的用户
GRANT REPLICATION CLIENT ON *.* TO 'maxscale_mon'@'10.0.0.%';    # 给予复制权限,用于复制服务器状态类信息。

CREATE USER 'client'@'10.0.0.%' IDENTIFIED BY '123456';    # 创建一个用户测试的用户。
CREATE DATABASE somata;    # 创建一个测试用的数据库
GRANT ALL ON somata.* TO 'client'@'10.0.0.%';    # 授权所有权限。

以及创建一个密钥,用于生成在 MaxScale 配置中使用的密码。
主要是为了防止配置文件泄露导致密码暴露。

maxkeys    #自动生成密钥
# 这里将自动保存密钥到 /var/lib/maxscale/.secrets
maxpasswd <pw>    # 基于密钥,生成加密后的密码。
# 这里会返回加密后的密码,后面将会用于配置文件中的密码填写,注意复制。

注:如果不想在配置文件中使用加密的密码,则需要删除 .secrets 文件。

# 全局配置段,配置MaxScale服务器的运行参数
[maxscale]
threads=auto

# 以下的所有段落为MaxScale对外提供服务所需要的参数
# 注意“节”名称不能包含空格,如有需要可以使用-/_代替。
# 各个“节”有不同的作用,MaxScale根据type参数来判断各个“节”是干什么的,
# 而不是根据“节”的名称来判断的。
# 这里这个配置文件一共有四个type: server(后端服务器)
# monitor(监控), service(服务,可以理解为路由)
# listener(监听器,由于对外提供服务)
[server1]    # 指定服务器一的配置
type=server
address=10.0.0.101        # 指定服务器地址
port=63132                # 指定服务器端口
# socket=/var/lib/mysql/mysql.sock    # 指定服务器的unix socket路径
# 如果 MaxScale 和 MariaDB 在同一台主机上,可以使用这种方法连接
# 不过需要注意,socket 用法与 address/port 是冲突的,只能选其一。
# 同时需要注意 MariaDB 的权限配置。
protocol=MariaDBBackend    # 指定连接使用的协议。
# 这里使用的是 MariaDBBackend 是 MariaDB 开发的特殊协议,
# 可以加快 MaxScale 访问 MariaDB 的访问速度。

[server2]
type=server
address=10.0.0.102
port=3306
protocol=MariaDBBackend

[server3]
type=server
address=10.0.0.103
port=3306
protocol=MariaDBBackend

[MariaDB-Monitor]
type=monitor
module=mariadbmon    # 指定启用模块 mariadbmon
# 此模块为监控模块,针对 MariaDB 服务器使用的监控模块,基础功能是用于监控服务器的健康状态的。
# 同时此模块能判断主从,当主服务器发生故障时还能完成自动化故障转移的操作,当然这些功能需要
# 手动开启,这些会在后面说明的。
# 这些模块都是以 so 形式保存在 /usr/lib64/maxscale/ 目录中的。
# 注: 主服务器一定要确保关闭 read_only,否则将判定主服务器是一个不可用的服务器,这将导致整个集群不可用。
servers=server1,server2,server3    # 指定需要对哪些服务器进行监控
# 这里的 server1,server2,server3 与上面的后端服务器“节”名称对应。
user=maxscale    # 指定监控使用的用户
password=111E15EBF48383FE639F9E134A956826    # 指定密码
# 这里就是经过加密的密码,密码为123456。
monitor_interval=2000ms    # 指定监控间隔事件这里是2秒

[Read-Write-Service]
type=service
router=readwritesplit    # 指定启用模块,readwritesplit
# 注意虽然前面写的是router,但是后面跟的还是模块名称。
# 此模块为路由模块,用于读写分离使用,它同通过监控模块获取服务器主从信息,自动完成读写分离。
# 它会将所有读取类操作都优先分发给从服务器使用,而写入类操作全部发送给主服务器,
# 修改变量类的操作将发送到所有服务器。
servers=server1,server2,server3
user=maxscale
# 注意,这里填写的用户是用来进行用户认证的。
password=111E15EBF48383FE639F9E134A956826

[Read-Write-Listener]
type=listener
service=Read-Write-Service
# 这里指定的服务,需要与上面对应。
protocol=MariaDBClient
# 指定协议 MariaDBClient 也就是 MySQL 协议。
port=3306
# 指定端口
# 可以使用 UNIX 套接字,而不是端口监听。
# socket=default
# 默认 UNIX sock 路径为 /var/run/maxscale/maxscale.sock
# 注意 socket 和 port 是冲突的。

现在就完成了 MaxScale 的主从分离配置了,现在开始启动服务

systemctl start maxscale
# 配置防火墙
firewall-cmd --add-port=3306/tcp --permanent
firewall-cmd --reload

查询状态信息,这里也能看见,都正常工作了。

maxctrl list servers    # 查询后端服务器状态信息
maxctrl list services   # 查询 MaxScale 内部状态信息

maxctrl list servers
maxctrl list services

MaxScale 自动化故障转移

在开始制作故障转移之前需要了解 GTID(全局事务ID),他是由域ID(默认值为0,可以通过gtid_domain_id变量来进行修改)、服务器ID和事务事务ID组成的的全局唯一标识符,例如:0-100-22。
设立全局事务ID的目的是为了保证数据的高可用性,例如下图,原本A为主服务器,B、C为从服务器,采用默认异步复制方式。当A奔溃时,B和C分别完成了不同量的数据存储,如果没有GTID那么将无法得知B和C那个是最新的版本,这就有可能导致数据错乱,是非常危险的。现在有了GTID,那么就能非常轻易的识别出那个服务器中的内容是最新的了,并且可以将其提升为新的主服务器。
同时有了GTID那么就能非常轻松的实现中断恢复,而不用担心数据会有遗漏的问题,因为每一个事务都会标有一个全局唯一的GTID(记录在二进制日志文件中),只需要从对应的GTID开始恢复即可。
注:MariaDB默认就开启了GTID功能,当有事务提交时,将会生成全局唯一的GTID。
故障转移图

因为 MaxScale 会通过监控模块完成进行故障转移操作,所以需要给予'maxscale_mon'@'10.0.0.%' SUPER 和 RELOAD 权限。

GRANT SUPER, RELOAD ON *.* TO 'maxscale_mon'@'10.0.0.%';

从服务器需要开启二进制日志。
当主服务器挂了时,将会挑选一台从服务器提升主服务器使用,此时就需要使用二进制日志功能了。
从服务器可以选择开启read_only,MaxScale 会自动检测该值,当需要将从服务器提升未主服务器时,会自动关闭该属性。
在三台数据库服务进行配置,修改配置文件:

# file: /etc/my.cnf.d/mariadb-server.cnf

……
log-bin=bin-log
log-bin-index=bin-log.index
relay-log=relay-log
# 可选配置,MariaDB以从服务器运行时,将会开启。
relay-log-index=relay-log.index
# 上同
server-id=100       #注意不要使用相同的服务器ID号。
……

编辑MaxScale的配置文件

# file: /etc/maxscale.cnf

……
[MariaDB-Monitor]
type=monitor
module=mariadbmon
servers=server1,server2,server3
user=maxscale_mon
password=111E15EBF48383FE639F9E134A956826
monitor_interval=2000ms
#  编辑添加如下几行
replication_user=slaver
replication_password=111E15EBF48383FE639F9E134A956826
# 以上两行用于指定复制用户的用户名和密码
# 如果未指定,将使用user和password
auto_failover=true
# 指定开启自动故障转移
auto_rejoin=true
# 指定开启自动加入集群(将以从服务器模式加入)
……
[Read-Write-Service]
type=service
router=readwritesplit
servers=server1,server2,server3
user=maxscale
password=111E15EBF48383FE639F9E134A956826
# 这里追加几个模块运行时的选项
master_failure_mode=error_on_write
# 当主服务器挂了时,客户端的写入操作将会返回错误,服务器以只读模式运行。
# 如果没有设置此值,那么当客户端执行写入操作时,MaxScale将会直接断开连接。
master_reconnection=true
# 当此选项启用时,并且master_failure_mode 设置为 fail_on_write|error_on_write 时,
# 将会取消只读模式,客户端的写入请求将会被重新处理。
……

配置从服务器,这里需要重新配置从服务器,配置从服务器使用GTID,两台从服务器使用相同的命令即可:

stop slave;    # 停止从服务器
reset slave;   # 重置从服务器
CHANGE MASTER TO MASTER_HOST='10.0.0.101' ,MASTER_USER='slaver', MASTER_PORT=63132, MASTER_PASSWORD='123456', MASTER_USE_GTID=current_pos;
# 配置指定主服务器,注意,这里指定主服务器使用GTID MASTER_USE_GTID=current_pos
# MASTER_USE_GTID一个有三个可选项 slave_pos、current_pos、no
# slave_pos 选项将使用 gtid_slave_pos 变量指定的值
# current_pos 选项将使用 gtid_current_pos 变量指定的值
# 注意,gtid_current_pos、gtid_binlog_pos值是只读的
# gtid_current_pos 值是 gtid_binlog_pos 和 gtid_slave_pos 两个变量的并集
# gtid_binlog_pos 当服务器有事务提交时将设置该变量
start slave;
# 这样就完成配置了

# 注意,如果再从服务器上面提交了事务,那么它会产生 gtid_binlog_pos,这将有可能
# 导致 gtid_current_pos,需要使用以下命令来重置它:
# 注意,这样同时会重置二进制日志文件,需要谨慎使用。
# reset master;

重启 maxscale 服务器:

systemctl restart maxscale

MaxScale 测试

这里关于读写分离的测试就不做了,基本上都是没有问题的。还是来测试一下故障转移可用性吧:

# 首先先检查以下服务器
maxctrl list servers
# 手动关闭主服务器
mysqladmin shutdown
# 再次查看服务器
# 注意,这里需要稍微等待以下大概2~4秒,并不是立即生效的
maxctrl list servers
# 这里再重新启动服务器,看看是否会重新加入
systemctl start mariadb
# 注意,从服务器默认并没有设置 gtid_binlog_pos 值,当提升为主服务器时,此时其余的服务器
# 并不会指向该服务器(也就是server2),需要在server2上提交一个事务才能生成 gtid_binlog_pos
# 值,其余服务器才能将主服务器指向该 server2。如果 server2 已经设置了 gtid_binlog_pos
# 那么将不会有这些问题。这里我们可以先查看以下服务器状态:
maxctrl list servers
# 当我们向 MaxScale 提交事务后,就可以正常使用了。
mysql -uclient -p123456 -P3306 -h10.0.0.101 -e'create table test (id int)' somata
# 此时我们再查看server1服务器状态,它就会发生改变了
# 同时我们也能发现,GTID也发送了改变
maxctrl list servers
# 如果有需求,可以使用命令将主服务器重新迁移回 server1
maxctrl call command mariadbmon switchover MariaDB-Monitor server1 server2
# 再次查看服务器
maxctrl list servers

maxctrl list servers
mysqladmin shutdown; maxctrl list servers
systemctl start mariadb; maxctrl list servers
mysql -uclient -p123456 -P3306 -h10.0.0.101 -e'create table test (id int)' somata; maxctrl list servers
maxctrl call command mariadbmon switchover MariaDB-Monitor server1 server2;maxctrl list servers

MaxScale 远程管理使用

MaxScale 开发了新的管理接口(reset API),使用了HTTP协议,用户认证也将基于 HTTP 协议完成。如果需要基于 MaxScale 做开发也就会变得更加方便,同时新的管理工具 maxctrl 也使用了该接口,老版的管理工具 maxadmin 和 API 由于在安全方面存在问题即将被废弃。
由于使用HTTP协议,所以可以MaxScale也支持 HTTPS,同时为了增强安全性,也开启了证书的双向认证。也就是说当客户端连接服务器时需要提供客户端的公钥用于认证客户端是否有效,客户端也将验证服务器证书,当然前提是这些证书都必须由同一CA颁发的,否者将无法完成认证。

默认 MaxScale 就开启了reset API,现在创建一下证书文件,然后配置 MaxScale 使用证书即可。

# 首先是创建CA服务的证书文件
mkdir -p /etc/pki/CA/private
mkdir /etc/pki/CA/newcerts
cd /etc/pki/CA
openssl genrsa -out private/cakey.pem 2048
openssl req -new -x509 -key private/cakey.pem -out cacert.pem # 这里的证书创建过程就省略不写了。
# 不过需要注意的是,必须要保证后面服务器证书申请的开头部分必须与证书开头相同,否则无法通过CA签发证书。
# 同时需要注意,颁发的服务器名称(commonName)需要与主机名称(FQDN)对应,必须要能解析到。
touch index.txt
echo "01" > serial
# 创建 MaxScale 服务器证书
cd /var/lib/maxscale/
openssl genrsa -out maxscale.key 2048
openssl req -new -key maxscale.key -out maxscale.csr
openssl ca -in maxscale.csr -out maxscale.crt -days 365
# 创建客户端证书
mkdir ~/.cert/
cd ~/.cert/
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr
openssl ca -in client.csr -out client.crt -days 365

配置 MaxScale 使用证书:

[maxscale]
threads=auto
admin_host=0.0.0.0
# 指定监听 0.0.0.0, 默认监听 127.0.0.1
admin_port=8989
# 指定监听端口,默认就是 8989
admin_ssl_key=/var/lib/maxscale/maxscale.key
# 指定服务器密钥
admin_ssl_cert=/var/lib/maxscale/maxscale.crt
# 指定服务器公钥
admin_ssl_ca_cert=/etc/pki/CA/cacert.pem
# 指定CA证书
# 注意,只有以上三个参数都配置了,HTTPS 才会生效,并且将强制使用HTTPS
……

这里偷个懒,在 hosts 文件中编写主机名,最好是在DNS中配置,方便管理。

# file: /etc/hosts

……
10.0.0.101 server1    # 注意,这里我使用的主机名为 server1
# 如果使用不同的主机名需要手动修改。

然后再重新测试软件

systemctl restart maxscale # 重启服务器,使配置生效
# 测试是否可用
maxctrl -s --tls-key /root/.cert/client.key --tls-cert /root/.cert/client.crt --tls-ca-cert /etc/pki/CA/cacert.pem -h server1:8989 list servers
# 注意,一定要使用主机名,而不是IP地址,client会检测证书是否与主机名对应,这也就是为什么需要配置 hosts 的原因。

maxctrl SSL 连接

maxctrl 简易用法

maxctrl 使用方法:

maxctrl [OPTIONS] [COMMAND]
注:maxctrl 如果不指定 COMMAND 将会进入交互式,在交互式中可以直接输入
COMMAND 即可,不过由于未知原因,当启用 HTTPS 时,将无法使用交互式执行命令。
这些应该会在后续的更新中修复。

OPTIONS:
    -u --user <USERNAME>    指定用户
    -p --password <PASSWORD>    指定用户密码
    -h --hosts <HOST:PORT>    指定主机
    -t --timeout <TIME>    指定超时时间 [单位:毫秒]
    -q --quiet    静默输出,将不输出任何参数。
    --tsv    使用 TAB 作为分隔符
    -s --secure    指定启用 HTTPS 请求 [Bool 默认: false]
    --tls-key <FILE>    指定连接使用的私钥
    --tls-passphrase <PASS>    指定连接使用的私钥密码
    --tls-cert <FILE>    指定连接使用的公钥
    --tls-ca-cert <FILE>    指定CA公钥
    -n --tls-verify-server-cert    检测服务器证书是否有效 [Bool 默认: true]
    --version  显示软件版本包
    --help     查询帮助信息

COMMAND:
    # 以表格格式显示基础信息
    list servers  # 显示所有后端服务器
    list services # 显示所有服务,例如读写分离服务等
    list monitors # 显示所有监控信息
    list listeners <service name> # 显示监听信息
    list threads  # 显示线程
    list modules  # 显示模块
    list sessions # 显示所有用户进程
    list commands # 显示所有模块的可用指令
    # 在以上的基础上显示更加详细的服务信息
    show servers  # 显示所有后端服务器的详细信息
    show server <server name> # 显示后端服务器的详细信息
    show service <service name> # 显示服务的详细信息
    show services # 显示所有服务的详细信息
    show monitor <monitor name> # 显示监控的详细信息
    show monitors # 显示所有监控的详细信息
    show session <session name>   # 显示用户进程信息
    show sessions # 显示所有用户进程信息
    show module <module name>  # 显示模块的详细信息
    show modules  # 显示所有模块的详细信息
    # 对 MaxScale 做出修改类的命令,注意如果做出了修改,那么将会永久成效,默认配置文件 /etc/maxscale.cnf 中的冲突部分将不再生效。
    # 实际上做出了修改之后,maxscale 的配置会存放至 /var/lib/maxscale/maxscale.cnf.d/ 目录下。
    clear server <server name> <state>  # 清除服务的指定属性,例如 Maintenance(维护模式)
    drain server <server name>    # 等待指定服务的所有链接线程结束,会将服务器标注为维护模式(Maintenance),新的连接将不会发送给该服务器。
    destroy server <server name> # 销毁指定的服务器,指定服务器必须断开service和monitor连接
    link service <service name> <server name>  # 指定后端服务器连接 服务。
    link monitor <monitor name> <server name>  # 指定后端服务器连接 监控
    unlink service <service name> <server name>  # 指定断开服务与后端服务器的链接
    unlink monitor <monitor name> <server name>  # 指定断开监控与后端服务器的链接
    create user <name> <password>    # 创建一个用户,默认用户具有只读权限,如果想要创建为管理员用户可以添加参数 --type=admin
    destroy user <name>    # 删除一个用户
    # 注:这里只是其中的一些命令,详细可以去查看官方文档。

(完)
本文经「原本」原创认证,作者乾坤盘,访问yuanben.io查询【3CJJDEYB】获取授权信息。

最后修改:2020 年 03 月 25 日 10 : 04 AM
如果觉得我的文章对你有用,请随意赞赏