近期巴以冲突爆发,拦截率90%的铁穹防空系统当场被打到宕机。
我们在日常工作中,也会随着业务的增长,面临海量用户对于服务器的并发访问量造成的性能问题。为此,我们可以搭建数据库集群,实现主从分离和负载均衡,来提高系统的可用性和性能。
接下来,本文就介绍一下,如何利用Docker来搭建MySQL数据库集群,并实现主从分离(1主2从)。
为了防止Docker容器被意外删除或者需要重新创建容器时能够快速恢复数据,我们通常需要对MySQL数据库的配置文件和数据做持久化存储。
其中一种方案是将MySQL的配置文件和数据分别挂载到宿主机上的不同目录中,即将宿主机上的目录与容器内的目录进行关联,以保证数据的安全性和可靠性。这样,在容器被删除或者重新创建时,只需要重新挂载这些目录,即可快速恢复MySQL数据库的数据和配置。
在宿主机上分别创建 MySQL 数据存放的目录
此次我们将数据存放在/usr/local下面。
扩展:Linux数据存放问题有一个FHS (Filesystem Hierarchy Standard) 试图制定一个文件层次结构标准,不说这个标准是否一定合理,但学习一下还是很好的。
Where in the filesystem should I store shared data?
mkdir -p /usr/local/softwares/mysql/{3306,3310,3311}/{conf,data}
获得 MySQL 的初始配置文件
首次挂载文件时,如果在宿主机上找不到对应的配置文件,Docker会自动创建一个空文件。但是,这就会导致容器中的MySQL配置文件也为空,造成配置丢失。所以,为了避免这种情况,我们需要提前在宿主机中准备一个配置文件。
那,这个文件去哪找呢?
简单,我们先创建一个MySQL容器,直接将它的配置文件复制一份不就好了。
docker run -it --name mysqlx -e MYSQL_ROOT_PASSWORD=123 -d mysql
然后使用Docker复制工具,将容器内文件复制到宿主机对应目录。
docker cp mysqlx:/etc/mysql/my.cnf /usr/local/softwares/mysql/3306/conf/
现在,我们就可以开始搭建主服务器了。
data存放目录(/var/lib/mysql)可在默认生成的my.cnf中查看。
/var/lib/mysql-files 文件不挂载日志中会提示错误,所以也一并挂载上。
docker run -it \
--name mysql_3306 \
--privileged \
--network docker_net \
--ip 172.18.12.2 \
-p 3306:3306 \
-v /usr/local/software/mysql/3306/conf/my.cnf:/etc/mysql/my.cnf \
-v /usr/local/software/mysql/3306/data:/var/lib/mysql \
-v /usr/local/software/mysql/3306/mysql-files:/var/lib/mysql-files \
-e MYSQL_ROOT_PASSWORD=123 \
-d mysql
执行后,可通过 docker ps
查询一下,若不成功,可以通过 docker logs
查看一下报错日志。
现在只是创建了一个普通的服务器,接下来我们将其设置为主服务器。
修改宿主机中3306/conf/下面的my.cnf文件
default_authentication_plugin=mysql_native_password
将默认插件设置为
mysql_native_password
。在MySQL 8.0及以上版本中,默认的插件是caching_sha2_password
,而在低版本中,默认插件是mysql_native_password
。所以在某些软件或应用程序中,可能不兼容caching_sha2_password(Navicat中输入密码可能会乱码)。server-id=200
标识MySQL服务器的唯一ID。集群环境中,每个MySQL实例都需要一个唯一ID。
log_bin=master-logbin
开启二进制日志(binlog)功能并自定义名称。正如上面所说,主服务器执行sql后,会将操作记录写入binlog文件中,所以我们需要开启binlog功能,为了确保其唯一性、可识别性以及可维护性我们将名称自定义。
binlog_format=row
指定二进制日志的格式。MySQL支持三种格式:
STATEMENT
、ROW
和MIXED
。statement
格式以SQL语句的形式记录日志,row
格式以行的形式记录日志,mixed
格式根据具体情况自动选择记录日志的形式。row
格式在数据一致性和可靠性方面较好。
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
secure-file-priv= NULL
default_authentication_plugin=mysql_native_password
# Custom config should go here
!includedir /etc/mysql/conf.d/
server-id=200
log_bin=master-logbin
binlog_format=row
修改完成后,我们将主服务器(mysql_3306)重启,使配置生效。
docker restart mysql_3306
重启后,运行 docker ps
检查一下,正常运行后就表示主服务器配置成功啦!(不成功请检查配置文件)
容器运行成功后,我们使用Navicat测试一下,并创建一个slave用户来进行主从关联。
create user 'slave'@'%' IDENTIFIED WITH mysql_native_password BY '123';
GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'slave'@'%';
flush privileges;
从服务器搭建与主服务器搭建步骤基本一样。我们先搭建第一个从服务器。
将主服务器上的 my.cnf
配置文件复制到宿主机 3310/cnf/
下
docker cp mysql_3306:/etc/mysql/my.cnf /usr/local/softwares/mysql/3310/conf/
修改 3310/conf/
下面的 my.cnf
配置文件
relay_log=slave-01-relay
:指定中继日志文件的名称。中继日志用于存储从主服务器接收并准备复制到从服务器的日志事件。
read-only=1
:将从服务器设置为只读模式,这样可以防止对从服务器进行写操作。这是为了确保从服务器不会被意外修改数据,因为它的目的是用于复制主服务器的数据而不是进行写操作。后面使用用户来控制操作权限。
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
secure-file-priv= NULL
default_authentication_plugin=mysql_native_password
# Custom config should go here
!includedir /etc/mysql/conf.d/
server-id=201
log_bin=slave-01-bin
relay_log=slave-01-relay
read-only=1
然后创建并运行容器,注意修改ip、端口以及挂载文件路径
docker run -it \
--name mysql_3310 \
--privileged \
--network docker_net \
--ip 172.18.12.3 \
-p 3310:3306 \
-v /usr/local/software/mysql/3310/conf/my.cnf:/etc/mysql/my.cnf \
-v /usr/local/software/mysql/3310/data:/var/lib/mysql \
-v /usr/local/software/mysql/3310/mysql-files:/var/lib/mysql-files \
-e MYSQL_ROOT_PASSWORD=123 \
-d mysql
运行成功后,进入容器中MySQL
docker exec -it mysql_3310 bash
# 进入mysql
mysql -uroot -p123
配置主服务器
master_host 就是主服务器(mysql_3306)的容器ip,用户就是刚刚我们在主mysql下创建的slave用户。
MASTER_LOG_FILE表示主服务器当前正在写入的binlog文件名。MASTER_LOG_POS指的是主服务器中binlog文件的记录位置。过这两个参数的设置,从服务器可以定位到主服务器binlog文件的特定位置,并从该位置开始进行数据复制。
这两个参数的值,需要进入主服务器(mysql_3306)中的mysql中查询,查询命令
show master status;
change master to master_host='172.18.12.2', master_user='slave',master_password='123',MASTER_LOG_FILE='master-logbin.000002',MASTER_LOG_POS=156;
配置完成后启动
start slave;
验证
show slave status \G;
若这两个参数值为Yes,则表示创建成功。
第二个从服务器搭建与第一个一样,需要注意以下几点:
配置文件server-id
一定不能相同,如下示例:
server-id=202
log_bin=slave-02-bin
relay_log=slave-02-relay
read-only=1
创建容器时注意修改ip、端口和挂载的路径名称。
配置主服务器时,MASTER_LOG_FILE和MASTER_LOG_POS一定要从新进入主MySQL中查询(有可能会变,变化后,从1的参数值无需修改,只需将从2的值设置为最新的查询结果即可)。
分别在两个从MySQL上创建这个用户,后续从MySQL使用此账户登录。
create user 'sd'@'%' IDENTIFIED WITH mysql_native_password BY '123';
GRANT SELECT ON *.* TO 'sd'@'%';
flush privileges;
slave不小心配置错误后,可使用下面方法重置
关闭slave
stop slave;
重置slave
reset slave;
重新配置slave
启动slave
start slave;
show variables like 'log_bin';
show variables like '%datadir%';
show binary logs;
show binlog events in 'master-logbin.000001';
感谢大家读到这里,后续还会有其他相关文章,欢迎继续阅读。