安装docker的步骤、使用命令就不写了,本文章是基于会使用docker、linux基本命令的基础上来写的。
开始步骤:
- 拉取 mysql 镜像
bash
docker pull mysql:8.0.32
- 启动容器并运行mysql
a. 准备mysql的配置文件(该配置文件是:mysql:8.0.32直接启动后的翻译过后的原始配置文件)
bash
# 关于如何更改设置的建议,请参考
# http://dev.mysql.com/doc/refman/8.0/en/server-configuration-defaults.html
[mysqld]
#
# 去掉前导的 #,并设置用于 MySQL 中最重要的数据缓存的内存量。
# 对于专用服务器,从总内存开始设置为 70%,否则为 10%。
# innodb_buffer_pool_size = 128M
#
# 去掉前导的 # 以启用一个非常重要的数据完整性选项:在备份之间记录
# 二进制日志中的更改。
# log_bin
#
# 去掉前导的 # 以设置主要用于报告服务器的选项。
# 对于事务和快速 SELECT,默认值更快。
# 根据需要调整大小,尝试找到最佳值。
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
# 去掉前导的 # 以恢复到先前的 default_authentication_plugin 值,
# 这将提高与旧客户端的兼容性。有关背景信息,请参阅:
# https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_default_authentication_plugin
# default-authentication-plugin=mysql_native_password
skip-host-cache
skip-name-resolve
datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
secure-file-priv=/var/lib/mysql-files
user=mysql
pid-file=/var/run/mysqld/mysqld.pid
[client]
socket=/var/run/mysqld/mysqld.sock
!includedir /etc/mysql/conf.d/
重点:++将配置文件在计算机本地创建好,后面会用来挂载到docker里的mysql的my.cnf 文件++
++只需要在本地创建 3个 my.cnf 文件,复制上面的内容 ,再分别在文中任意位置,最好放当中 添加 server_id=100、server_id=101、server_id=102 属性即可(没有顺序,值也可以是1、2、3任意的,不同就行,作用只是标记启动的不同数据库拥有不同的id,如果3个数据库不在一个服务器上就不需要添加这个配置了)。++
bash
下面是挂载的内容解释:
-- 启动一个mysql将数据挂载到本地目录:/Users/wangqinmin/docker/mysql/master_slave/master_data
-- 配置文件挂载到,mysql8.0.32的my.cnf文件位置在/etc/my.cnf:/Users/wangqinmin/docker/mysql/master_slave/conf/master_conf/my.cnf:/etc/my.cnf
-- 日志文件挂载到:/Users/wangqinmin/docker/mysql/master_slave/log/master_log:/var/log/mysql
-- SELECT ... INTO OUTFILE 操作导出的文件挂载到:/Users/wangqinmin/docker/mysql/master_slave/file/mysql-files
b. 写好命令,开始执行
bash
docker run --name mysql_master_33066 -v /Users/wangqinmin/docker/mysql/master_slave/data/master_data:/var/lib/mysql -v /Users/wangqinmin/docker/mysql/master_slave/conf/master_conf/my.cnf:/etc/my.cnf -v /Users/wangqinmin/docker/mysql/master_slave/log/master_log:/var/log/mysql -v /Users/wangqinmin/docker/mysql/master_slave/file/mysql-files:/var/lib/mysql-files -p 33066:3306 -e MYSQL_ROOT_PASSWORD=wangqinmin -d mysql:8.0.32
docker run --name mysql_slave_33067 -v /Users/wangqinmin/docker/mysql/master_slave/data/slave1_data:/var/lib/mysql -v /Users/wangqinmin/docker/mysql/master_slave/conf/slave1_conf/my.cnf:/etc/my.cnf -v /Users/wangqinmin/docker/mysql/master_slave/log/slave1_log:/var/log/mysql -v /Users/wangqinmin/docker/mysql/master_slave/file/mysql_files_slave1:/var/lib/mysql-files -p 33067:3306 -e MYSQL_ROOT_PASSWORD=wangqinmin -d mysql:8.0.32
docker run --name mysql_slave_33068 -v /Users/wangqinmin/docker/mysql/master_slave/data/slave2_data:/var/lib/mysql -v /Users/wangqinmin/docker/mysql/master_slave/conf/slave2_conf/my.cnf:/etc/my.cnf -v /Users/wangqinmin/docker/mysql/master_slave/log/slave2_log:/var/log/mysql -v /Users/wangqinmin/docker/mysql/master_slave/file/mysql_files_slave2:/var/lib/mysql-files -p 33068:3306 -e MYSQL_ROOT_PASSWORD=wangqinmin -d mysql:8.0.32
- 从上面的挂载目录命名就可以看出,我准备将 33066 作为主数据库,33067和33068做为从数据库
4. ++主从复制就是在数据库上做配置的设置(重点在这里,但是很简单,就几条命令)++
1. 进入33066主库 docker容器中
bash
docker exec -it mysql_master_33066 /bin/bash
a. 首先 mysql -uroot -p 进入mysql ,或者用 Navicat 工具连接
b. 执行以下两条命令:
bash
-- 创建名字为:copy_file_wangqinmin ,密码为:wangqinmin ,访问ip为任意ip的用户
CREATE USER 'copy_file_wangqinmin'@'%' IDENTIFIED BY 'wangqinmin';
-- 为名字是 copy_file_wangqinmin 的用户,只设置 REPLICATION SLAVE (复制数据的权限)
GRANT REPLICATION SLAVE ON *.* TO 'copy_file_wangqinmin'@'%';
-- mysql8.0.32 需要执行这个命令(搭建完成后,发现没有连接成功,看错误日志后添加的这一段命令)
-- 否则会有错误日志:
-- error connecting to master 'copy_file_wangqinmin@192.168.1.3:33066' - retry-time: 60 retries: 1 message: Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection.
ALTER USER 'copy_file_wangqinmin'@'%' IDENTIFIED WITH 'mysql_native_password' BY 'wangqinmin';
-- 刷新权限
FLUSH PRIVILEGES;
c. 重启主库和从库
bash
docker restart mysql_master_33066 mysql_slave_33067 mysql_slave_33068
d. 在主库上执行以下命令,并记下 "File" 和 "Position" 的值:
bash
SHOW MASTER STATUS;
我这里获取到的数据为:
因为mysql都在docker内部安装,所以容器的本地ip是127.0.0.1,但是本机外部的本地ip也是127.0.0.1,所以需要查询外部电脑的ip地址:
我的ip地址是: 192.168.1.3
2. 进入33067从库 docker容器中
bash
docker exec -it mysql_slave_33067 /bin/bash
进入mysql中 或者 用 Navicat 工具连接后,分别执行以下3条命令:
bash
-- 停止从库的复制进程。这是为了确保在修改主从配置时,不会有正在运行的复制进程。
STOP SLAVE;
-- 指定从库要去主库的哪个位置开始复制数据。
CHANGE MASTER TO
MASTER_HOST='192.168.1.3',
MASTER_PORT=33066,
MASTER_USER='copy_file_wangqinmin',
MASTER_PASSWORD='wangqinmin',
MASTER_LOG_FILE='binlog.000002',
MASTER_LOG_POS=721;
-- 启动从库的复制进程,开始从主库复制数据。
START SLAVE;
3. 进入33068从库 docker容器中
bash
docker exec -it mysql_slave_33068 /bin/bash
进入mysql中 或者 用 Navicat 工具连接后,分别执行以下3条命令:
-- 停止从库的复制进程。这是为了确保在修改主从配置时,不会有正在运行的复制进程。
STOP SLAVE;
-- 指定从库要去主库的哪个位置开始复制数据。
CHANGE MASTER TO
MASTER_HOST='192.168.1.3',
MASTER_PORT=33066,
MASTER_USER='copy_file_wangqinmin',
MASTER_PASSWORD='wangqinmin',
MASTER_LOG_FILE='binlog.000002',
MASTER_LOG_POS=721;
-- 启动从库的复制进程,开始从主库复制数据。
START SLAVE;
++解释:++
- ++
MASTER_HOST='
192.168.1.3'
: 指定主库的 IP 地址。++ - ++
MASTER_PORT=33066
: 指定主库的端口号。++ - ++
MASTER_USER='copy_file_wangqinmin'
: 指定用于连接主库的用户。++ - ++
MASTER_PASSWORD='wangqinmin'
: 指定主库用户的登录密码。++ - ++
MASTER_LOG_FILE='binlog.
++ 000002++'
: 指定主库的二进制日志文件。++ - ++
MASTER_LOG_POS=721
: 指定从主库的从哪个二进制日志位置开始复制数据。++
最后一步:查看从库的状态,确定从库是否已经连接到主库,是否能够复制文件和sql:
在从库上执行以下命令:
SHOW SLAVE STATUS;
确保 "Slave_IO_Running" 和 "Slave_SQL_Running" 均为 "Yes"
++如果一直没有连接上,可以尝试先重启主库,再重启从库。如果还不行,就看看是不是ip或者是参数填写错误。++
++或者查看错误日志:++
执行命令查看错误日志(这里是我不断调试过程中发现的错误日志):SHOW SLAVE STATUS;
给大家看一下成功的结果:
这时候向主库 【创建数据库,添加数据,修改数据等等】,导致数据变化的操作。从库都会实时的进行数据变更。
有一点要注意的是,虽然实现了主从复制,但是依然会有延迟,并且可能由于:网络、IO、CPU等因素的影响,最终会导致数据的不一致问题,这个问题不能被完全解决,只能优化,同时某些业务如果要求数据一致的情况下,还是需要直接去读主库。
注意!!!!!!!,还没有完 。
上面只是搭建,还有关闭、启动数据库,也是有步骤的。
思想很简单:
1. 先关闭从库,再关闭主库;
2. 先启动主库,再启动从库。
关闭:
bash
我们需要:
1. 先关闭从库的复制功能 (这个是有顺序的,必须先执行)
STOP SLAVE;
2. 然后关闭主库
systemctl stop mysql 我这里是docker ,就直接: docker stop 容器ID
3. 再关闭多个从库(我这里是两个)
systemctl stop mysql 我这里是docker ,就直接: docker stop 容器ID
启动:
1. 先启动主库
systemctl start mysql
2. 再启动多个从库
systemctl start mysql
3. 从库执行 (每个从库都执行)
START SLAVE;
4. 然后看一下状态是否正确 (正确就可以了)
SHOW SLAVE STATUS;
- 要完成读写分离的话,我使用 sharding jdbc来完成。让主库完成 (增、删、改的操作),让从库的轮询访问来完成读的操作。
~~未完待续