mysql搭建主要参照了这位大牛的博客docker篇-(docker-compose搭建mysql高可用主从集群)
本文实现了一主二从的部署,第二个从库以及nginx与主库放在了一台服务器上
节点名 | ip |
---|---|
mysql-master | 192.168.136.131:3306 |
mysql-slave1 | 192.168.136.132:3306 |
mysql-slave2 | 192.168.136.131:3307 |
# 创建mysql目录存放myslq相关文件
mkdir /docker/mysql
# 创建init目录存放init脚本
mkdir /docker/mysql/init
# 创建master目录存放master相关文件
mkdir /docker/mysql/init/master
# 创建mysql目录存放myslq相关文件
mkdir /docker/mysql
# 创建init目录存放init脚本
mkdir /docker/mysql/init
# 创建slave目录存放slave相关文件
mkdir /docker/mysql/init/slave
# 下载默认latest版本mysql
# 也可以在mysql输入指定版本,如:docker pull mysql:8.0.25
docker pull mysql
#将master初始化脚本写入到init/master目录下
cat > docker/mysql/init/master/create_sync_user.sh <<EOF
#!/bin/bash
#定义用于同步的用户名
MASTER_SYNC_USER=\${MASTER_SYNC_USER:-sync_admin}
#定义用于同步的用户密码
MASTER_SYNC_PASSWORD=\${MASTER_SYNC_PASSWORD:-123456}
#定义用于登录mysql的用户名
ADMIN_USER=\${ADMIN_USER:-root}
#定义用于登录mysql的用户密码
ADMIN_PASSWORD=\${ADMIN_PASSWORD:-123456}
#定义运行登录的host地址
ALLOW_HOST=\${ALLOW_HOST:-%}
#定义创建账号的sql语句,mysql8以下版本 【WITH mysql_native_password】这段需要删除
CREATE_USER_SQL="CREATE USER '\$MASTER_SYNC_USER'@'\$ALLOW_HOST' IDENTIFIED WITH mysql_native_password BY '\$MASTER_SYNC_PASSWORD';"
#定义赋予同步账号权限的sql,这里设置两个权限,REPLICATION SLAVE,属于从节点副本的权限,REPLICATION CLIENT是副本客户端的权限,可以执行show master status语句
GRANT_PRIVILEGES_SQL="GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO '\$MASTER_SYNC_USER'@'\$ALLOW_HOST';"
#定义刷新权限的sql
FLUSH_PRIVILEGES_SQL="FLUSH PRIVILEGES;"
#执行sql
mysql -u"\$ADMIN_USER" -p"\$ADMIN_PASSWORD" -e "\$CREATE_USER_SQL \$GRANT_PRIVILEGES_SQL \$FLUSH_PRIVILEGES_SQL"
EOF
# 创建并编辑docker-compose.yml
vi /docker/mysql/docker-compose.yml
# 填写如下内容
version: '3'
services:
mysql-master:
image: mysql:latest
container_name: mysql-master
environment:
MYSQL_ROOT_PASSWORD: "123456"
MASTER_SYNC_USER: "sync_admin"
MASTER_SYNC_PASSWORD: "123456"
ADMIN_USER: "root"
ADMIN_PASSWORD: "123456"
# 允许同步地址根据自身需要进行修改
ALLOW_HOST: "192.168.136.%"
TZ: "Asia/Shanghai"
ports:
- 3306:3306
restart: always
hostname: mysql-master
volumes:
- ./init/master:/docker-entrypoint-initdb.d
command:
- "--server-id=1"
- "--character-set-server=utf8mb4"
- "--collation-server=utf8mb4_unicode_ci"
- "--log-bin=mysql-bin"
- "--sync_binlog=1"
# 进入mysql文件夹
cd /docker/mysql
# docker-compose命令启动
docer-compose up -d
# 使用docker ps查看正在运行的container
docker ps
# 使用docker logs命令查看容器的运行情况
docker logs mysql-master
查看到初始化脚本允许后,mysql重新启动成果,mysql-master就、则配置完成
mysql-slave的安装方法同mysql-master,但是sh脚本及docker-compose.yml存在较大差异
#将master初始化脚本写入到init/master目录下
cat > docker/mysql/init/slave/slave.sh <<EOF
#!/bin/bash
#定义连接master进行同步的账号
SLAVE_SYNC_USER="\${SLAVE_SYNC_USER:-sync_admin}"
#定义连接master进行同步的账号密码
SLAVE_SYNC_PASSWORD="\${SLAVE_SYNC_PASSWORD:-123456}"
#定义slave数据库账号
ADMIN_USER="\${ADMIN_USER:-root}"
#定义slave数据库密码
ADMIN_PASSWORD="\${ADMIN_PASSWORD:-123456}"
#定义连接master数据库host地址
MASTER_HOST="\${MASTER_HOST:-%}"
#等待10s,保证master数据库启动成功,不然会连接失败
sleep 10
#连接master数据库,查询二进制数据,并解析出logfile和pos,这里同步用户要开启 REPLICATION CLIENT权限,才能使用SHOW MASTER STATUS;
RESULT=\`mysql -u"\$SLAVE_SYNC_USER" -h\$MASTER_HOST -p"\$SLAVE_SYNC_PASSWORD" -e "SHOW MASTER STATUS;" | grep -v grep |tail -n +2| awk '{print \$1,\$2}'\`
#解析出logfile
LOG_FILE_NAME=\`echo \$RESULT | grep -v grep | awk '{print \$1}'\`
#解析出pos
LOG_FILE_POS=\`echo \$RESULT | grep -v grep | awk '{print \$2}'\`
#设置连接master的同步相关信息
SYNC_SQL="change master to master_host='\$MASTER_HOST',master_user='\$SLAVE_SYNC_USER',master_password='\$SLAVE_SYNC_PASSWORD',master_log_file='\$LOG_FILE_NAME',master_log_pos=\$LOG_FILE_POS;"
#开启同步
START_SYNC_SQL="start slave;"
#查看同步状态
STATUS_SQL="show slave status\G;"
mysql -u"\$ADMIN_USER" -p"\$ADMIN_PASSWORD" -e "\$SYNC_SQL \$START_SYNC_SQL \$STATUS_SQL"
EOF
# 创建并编辑docker-compose.yml
vi /docker/mysql/docker-compose.yml
# 填写如下内容
version: '3'
services:
mysql-slave:
image: mysql:latest
container_name: mysql-slave
environment:
MYSQL_ROOT_PASSWORD: "123456"
SLAVE_SYNC_USER: "sync_admin"
SLAVE_SYNC_PASSWORD: "123456"
ADMIN_USER: "root"
ADMIN_PASSWORD: "123456"
# 填写mysql-master ip
MASTER_HOST: "192.168.136.131"
TZ: "Asia/Shanghai"
ports:
- 3306:3306
volumes:
- ./init/slave:/docker-entrypoint-initdb.d
command:
- "--server-id=2"
- "--character-set-server=utf8mb4"
- "--collation-server=utf8mb4_unicode_ci"
# 进入mysql文件夹
cd /docker/mysql
# docker-compose命令启动
docer-compose up -d
# 使用docker ps查看正在运行的container
docker ps
# 使用docker logs命令查看容器的运行情况
docker logs mysql-slave
上翻查阅log,可以发现Slave_IO_Running、Slave_SQL_Running两个属性已经是Yes状态,标识主从复制已经完成,验证数据同步我就不演示了。
我采用一个主一从在一个服务器上,另一个从库在另外一台服务器上,通过nginx实现正常情况下两个服务器中的一主一从备份,单独的从库服务器挂掉时,主库上的从库会作为备用顶替上。
cat > nginx.conf <<EOF
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
# 添加stream模块,实现tcp反向代理
stream {
include /opt/nginx/stream/conf.d/*.conf; #加载 /opt/nginx/stream/conf.d目录下面的所有配置文件
}
EOF
mkdir -p conf.d/stream
cat > conf.d/stream/mysql.conf <<EOF
proxy_timeout 30m;
upstream mysql-slave-cluster{
#docker-compose.yml里面会配置固定mysql-slave的ip地址,这里就填写固定的ip地址
server 192.168.136.132:3306 weight=1;
server 192.168.136.131:3307 weight=1 backup; #备用数据库,当上面的数据库挂掉之后,才会使用此数据库,也就是如果上面的数据库没有挂,则所有的流量都很转发到上面的主库
}
server {
listen 0.0.0.0:3308;
proxy_pass mysql-slave-cluster;
}
EOF
version: '3'
services:
mysql-master:
image: mysql:latest
container_name: mysql-master
environment:
MYSQL_ROOT_PASSWORD: "123456"
MASTER_SYNC_USER: "sync_admin"
MASTER_SYNC_PASSWORD: "123456"
ADMIN_USER: "root"
ADMIN_PASSWORD: "123456"
# local是给另外一台服务器上从数据库使用
ALLOW_HOST_LOCAL: "192.168.136.%"
# nonlocal是给本机的第二个从数据库使用
ALLOW_HOST_NONLOCAL: "10.10.%.%"
TZ: "Asia/Shanghai"
ports:
- 3306:3306
restart: always
hostname: mysql-master
volumes:
- ./init/master:/docker-entrypoint-initdb.d
command:
- "--server-id=1"
- "--character-set-server=utf8mb4"
- "--collation-server=utf8mb4_unicode_ci"
- "--log-bin=mysql-bin"
- "--sync_binlog=1"
networks:
mysql:
ipv4_address: "10.10.10.10"
mysql-slave2:
image: mysql:latest
container_name: mysql-slave2
restart: always
environment:
MYSQL_ROOT_PASSWORD: "123456"
SLAVE_SYNC_USER: "sync_admin"
SLAVE_SYNC_PASSWORD: "123456"
ADMIN_USER: "root"
ADMIN_PASSWORD: "123456"
MASTER_HOST: "10.10.10.10"
TZ: "Asia/Shanghai"
ports:
- 3307:3307
volumes:
- ./init/slave:/docker-entrypoint-initdb.d
command:
- "--server-id=3"
- "--character-set-server=utf8mb4"
- "--collation-server=utf8mb4_unicode_ci"
networks:
- mysql
networks:
mysql:
driver: bridge
ipam:
driver: default
config:
- subnet: "10.10.0.0/16"
#!/bin/bash
#定义用于同步的用户名
MASTER_SYNC_USER=${MASTER_SYNC_USER:-sync_admin}
#定义用于同步的用户密码
MASTER_SYNC_PASSWORD=${MASTER_SYNC_PASSWORD:-123456}
#定义用于登录mysql的用户名
ADMIN_USER=${ADMIN_USER:-root}
#定义用于登录mysql的用户密码
ADMIN_PASSWORD=${ADMIN_PASSWORD:-123456}
#定义运行登录的host地址
ALLOW_HOST_LOCAL=${ALLOW_HOST_LOCAL:-%}
ALLOW_HOST_NONLOCAL=${ALLOW_HOST_NONLOCAL:-%}
#定义创建账号的sql语句
CREATE_LOCAL_USER_SQL="CREATE USER '$MASTER_SYNC_USER'@'$ALLOW_HOST_LOCAL' IDENTIFIED WITH mysql_native_password BY '$MASTER_SYNC_PASSWORD';"
CREATE_NONLOCAL_USER_SQL="CREATE USER '$MASTER_SYNC_USER'@'$ALLOW_HOST_NONLOCAL' IDENTIFIED WITH mysql_native_password BY '$MASTER_SYNC_PASSWORD';"
#定义赋予同步账号权限的sql,这里设置两个权限,REPLICATION SLAVE,属于从节点副本的权限,REPLICATION CLIENT是副本客户端的权限,可以执行show master status语句
GRANT_PRIVILEGES_LOCAL_SQL="GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO '$MASTER_SYNC_USER'@'$ALLOW_HOST_LOCAL';"
GRANT_PRIVILEGES_NONLOCAL_SQL="GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO '$MASTER_SYNC_USER'@'$ALLOW_HOST_NONLOCAL';"
#定义刷新权限的sql
FLUSH_PRIVILEGES_SQL="FLUSH PRIVILEGES;"
#执行sql
mysql -u"$ADMIN_USER" -p"$ADMIN_PASSWORD" -e "$CREATE_LOCAL_USER_SQL $CREATE_NONLOCAL_USER_SQL $GRANT_PRIVILEGES_LOCAL_SQL $GRANT_PRIVILEGES_NONLOCAL_SQL $FLUSH_PRIVILEGES_SQL"
如果集群建立有问题,首先排查每个节点是否正在运行,如果节点未运行,可以看下节点启动时的logs,来排查问题
# 通过容器的名称或id查看容器的运行logs
docker logs 【container name/id】
可根据logs中的errors等逐个排查
我采用一主一从+一从的方式,所以需要注意两台服务器中ip的关系,同服务器内通过docker-compose.yml定义了内部地址,使用内部地址进行通信,不同服务器使用局域网地址进行通讯,ip混乱会导致从库复制同步失败
本章主要介绍通过docker、docker-compose配置mysql主从复制以及从库集群级: