title | date |
---|---|
Docker部署:Mysql主从 |
2019-02-18 12:21:32 -0800 |
博主有个应用,为了提高可用性,打算使用 Mysql 的主从复制。同时,由于 DB 也是部署在容器中的,所以在操作之后,也已此文记录一下。
博主主力机为 Windows10,所以是直接 Hyper-V 创建的虚拟机安装 CentOS 7.6 操作系统。
下文出现的宿主机命令,仅针对 Redhat/CentOS ,其他 Linux 系统,需要自行使用同类的命令。
可直接根据:https://docs.docker.com/install/linux/docker-ce/centos/ 完成 Docker 安装。
通过命令行:docker info 进行验证。
推荐将 mysql 的数据和配置放在宿主机目录上,所以需要提前规划目录。
为了演示,我们准备在一台机器上直接部署三个 mysql 实例,实现一主两从。那么目录准备如下:
- 首先
mkdir /opt/db_storage
创建数据库相关目录(我个人喜欢把/opt 作为存储目录) - 按需创建三个目录,用于映射到容器。
/opt/db_storage/
mysql01/
data/ # 用于存放DB数据
conf/
my.cnf # 配置文件
mysql02/ # 子目录同 mysql01
mysql03/ # 子目录同 mysql01
首先,提前准备好 mysql 镜像(也可以直接 docker run 的时候自动下载),如:mysql:8.0.15 mysql:5.7.22
对于 Mysql Master-Salve 来说,第一个要点就是配置 my.cnf。
假设我们把 mysql01 目录作为 Master,那么配置文件简化内容如下:
# mysql01/conf/my.cnf Master实例的配置
[mysqld]
log-bin=mysql-bin # 开启二进制日志
server_id=1 # 配置server_id,经测试 server-id=1 也可以
# mysql02/conf/my.cnf Slave1 实例的配置
[mysqld]
server-id=12 # 根据个人喜好设置,但必须要唯一
# mysql03/conf/my.cnf Slave2 实例的配置
[mysqld]
server-id=13 # 根据个人喜好设置,但必须要唯一
注意:主要就是 master 实例开启日志,然后 slave 实例配置唯一的 ID。
由于是一台机器上,运行三个实例,所以用 host 网络模式就不是太合适,所以我们选择使用桥接网络模式。
因此,我们执行的命令如下:
# 创建 Master 容器
docker run --name mysql-master \
-v /opt/db_storage/mysql01/conf:/etc/mysql/conf.d \
-v /opt/db_storage/mysql01/data:/var/lib/mysql \
-p 8001:3306
-e MYSQL_ROOT_PASSWORD=mima \
-d mysql:8.0.15
# 创建 Slave1 容器
docker run --name mysql-master \
-v /opt/db_storage/mysql02/conf:/etc/mysql/conf.d \
-v /opt/db_storage/mysql02/data:/var/lib/mysql \
-p 8002:3306
-e MYSQL_ROOT_PASSWORD=mima \
-d mysql:8.0.15
# 创建 Slave2 容器
docker run --name mysql-master \
-v /opt/db_storage/mysql03/conf:/etc/mysql/conf.d \
-v /opt/db_storage/mysql03/data:/var/lib/mysql \
-p 8003:3306
-e MYSQL_ROOT_PASSWORD=mima \
-d mysql:8.0.15
这里面主要的区别,就是映射到容器的目录以及端口映射有差异。
至此,我们的容器也准备好了。
经过前两个步骤的准备,现在我们只需要连接到 Mysql 实例,然后开启主从复制即可。
对于 Master 实例,我们只需要确认下 log-bin 是否正常启用即可。所以连接到 Server 之后,执行如下命令即可:
show master status;
结果如下图:
对于 Slave 实例,略麻烦一些,简单思考一下,如果我们要去复制(备份)一个 DB 的内容,很明显需要知道要到什么地方去复制。那么这个动作对应的语句就是:
CHANGE MASTER TO
MASTER_HOST='192.168.1.201', -- Master 实例的IP
MASTER_PORT=8001, -- Master 实例的端口
MASTER_USER='root', -- Master 实例的用户名
MASTER_PASSWORD='mima', -- Master 实例的用户名
MASTER_LOG_FILE='mysql-bin.000003', -- 注意,此处很关键,需要配置 bin log 文件的名称,如上图 Master 状态。
MASTER_LOG_POS=0; -- 这个更重要,标记从日志的哪个位置开始复制。
注意,此处为了简单直接以 root 用户连接到 master,实际使用中,建议单独创建一个账号用于同步。
如何创建一个账号用于同步呢?
-- 创建用户,其中 mima 是登录密码,其中 % 表示不限制客户端IP。
CREATE USER 'for-slave'@'%' IDENTIFIED WITH mysql_native_password BY 'mima';
--也可以使用IP,限制客户端访问
CREATE USER 'for-slave'@'192.168.1.201' IDENTIFIED WITH mysql_native_password BY 'mima';
-- 对账户授权
GRANT REPLICATION SLAVE ON *.* TO 'for-slave'@'%'
-- 刷新授权表
flush privileges;
注意:以上操作需要在 Master 实例上执行。
以上仅仅是配置了从哪儿同步数据,那么要开始同步,则需要执行:
start slave; -- 开始同步
--当然,猜测一下, 停止同步就应该是
-- stop slave;
接着,我们还是要确认下 Slave 的状态:
show slave status;
结果如图:
对于多个 Slave 实例,用同样的方式处理即可。
测试就比较直接,操作 Master 实例,查看 Slave 实例,是否也有同样的变化即可。
这是一个非常常见的需求,一个 Server 下一般都会有很多的 DB,我们需要选择我们关注的 DB 来进行复制即可。可以有如下两种方式。
这个方案比较容易理解,直接从源头上只记录需要复制的表的日志。这样从库也只能复制这些变化。实现如下:
# 编辑 master 实例的 my.cnf 配置文件。加入如下节点
[mysqld]
log-bin=mysql-bin
server_id=1
binlog-do-db=要复制的DB # 如果是有多个,多复制几行即可。
# 那如果我只是想要排除几个DB呢?
binlog-ignore-db=要排除的DB # 如果是有多个,同样多复制几行。
很明显,这个方案是从源头切掉了 binlog,如果后续要多复制几个 DB,那就不好处理,因为压根没有记录 binlog。
遗留问题一:都配置上会有什么效果呢?
做法也和方案一比较类似,不过是在 slave 的配置中增加类似配置:
# 编辑 slave 实例的 my.cnf 配置
replicate-do-db=要复制的DB # 如果是有多个,多复制几行即可。
replicate-ignore-db=要排除的DB # 如果是有多个,多复制几行即可。
为了避免操作从库,建议在从库的配置中,增加 read_only=true,此配置对 root 账户无效。参考https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_read_only。
这个也是博主实际的场景。我的做法是,现再现有的实例上,启用 binlog。然后再使用 mysqldump 将数据同步到从库(注意,此时从库还没有 start slave),同步完成后,再执行 start slave 来启用。
- Docker 报错:
WARNING: IPv4 forwarding is disabled. Networking will not work.
这是由于宿主机没有配置 IPV4 转发导致的,解决方案如下:
sudo vi /usr/lib/sysctl.d/00-system.conf # 修改配置
# 添加如下行
net.ipv4.ip_forward=1
# 保存好之后,重启网络服务
systemctl restart network
- 使用 mysqldump 备份 DB 时,出现
Table 'xxx' doesn't exist when using LOCK TABLES
这是由于 DB 中已经删除中该表,在该表的物理文件还在,进入 DB 表存储目录,对指定的 table 进行删除即可(慎重,不要误删)。
- 使用 mysqldump 备份时,出现
Authentication plugin 'caching_sha2_password' cannot be loaded: /usr/lib64/mysql/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory" when trying to connect
这是由于 Mysql 8.x 的安全策略,导致无法直接使用密码进行备份。解决办法就是直接连接到该 Mysql Server,执行如下修改:
-- 允许使用native password
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '<root账户密码>';
-- 刷新授权表
flush privileges;