docker-compose安裝mysql主從集群
- 為什么要使用mysql主從集群
- 基于docker,手動搭建mysql主從集群
- 拉取mysql鏡像
- 啟動鏡像
- 重新啟動鏡像,并設定master需要配置的引數
- 進入容器,創建主從同步賬號
- 啟動slave容器,實作主從同步
- 測驗同步
- 基于docker,使用腳本的方式實作主從
- 撰寫master用于創建同步賬號的腳本
- 啟動mysql-master,掛載腳本
- 撰寫mysql-slave腳本
- 啟動mysql-slave
- 測驗同步資料
- 使用docker-compose,實作一鍵部署一主二從
- 撰寫docker-compose.yml檔案
- 運行docker-compose.yaml
- 查看三臺容器的日志
- mysql-master
- mysql-slave1
- mysql-slave2
- 測驗資料同步
- mysql-master
- mysql-slave1
- mysql-slave2
- 加入nginx,實作slave的負載均衡
- 創建nginx負責均衡的組態檔
- 創建nginx.conf,開啟stream支持
- 撰寫mysql.conf
- 修改docker-compose.yml
- 執行docker-compose
- 使用navicat連接從庫
- 在mysql-master中創建測驗資料,并進入navicat查看情況
- 寫在最后
為什么要使用mysql主從集群
簡單來說,如果對資料庫的讀和寫都在同一個資料庫服務器中操作,資料庫的壓力會變大,導致讀寫性能會下降,為了提升資料庫性能,優化用戶體驗,可以通過做主從復制(讀寫分離)來減輕主資料庫的負載, 而且如果主資料庫宕機,可快速將業務系統切換到從資料庫上,可避免資料丟失,
在這里,我為什么使用docker來模擬mysql主從集群,是因為為了切合我博客的標題,使用docker容器化的方式實作mysql主從集群一鍵部署
基于docker,手動搭建mysql主從集群
拉取mysql鏡像
這里使用的是mysql8.0.13版本的鏡像,為了防止后續鏡像發生變化,所以使用一個相對穩定版本來部署
docker pull mysql:8.0.13
啟動鏡像
啟動鏡像,測驗鏡像是否能正常運行
docker run --name mysql -e MYSQL_ROOT_PASSWORD="123456" -d mysql:8.0.13

重新啟動鏡像,并設定master需要配置的引數
#關掉之前的鏡像
docker rm -f mysql
#啟動新的鏡像,設定server-id和開啟logbin
docker run --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD="123456" -d mysql:8.0.13 --server-id=1 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --log-bin=mysql-bin --sync_binlog=1
進入容器,創建主從同步賬號
#查看容器當前ip網段,后續創建同步賬號會需要
docker inspect mysql
docker exec -ti mysql bash
mysql -uroot -p123456
CREATE USER 'sync_root'@'172.17.%.%' IDENTIFIED BY 'sync_123456';
GRANT REPLICATION SLAVE ON *.* TO 'sync_root'@'172.17.%.%';
FLUSH PRIVILEGES;
#查看master的binlog資訊
SHOW MASTER STATUS;


啟動slave容器,實作主從同步
#啟動容器,等待mysql正常啟動
docker run --name slave -e MYSQL_ROOT_PASSWORD="123456" -d mysql:8.0.13 --server-id=2 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
#進入容器,連接master,然后開啟同步
docker exec -ti slave bash
mysql -uroot -p123456
# 這里master_host就是剛剛看到的master的ip,master_user就是我們創建用于同步的賬號,master_log_file和master_log_pos就是通過show master status獲得到的
CHANGE MASTER TO MASTER_HOST='172.17.0.2',MASTER_USER='sync_root',MASTER_PASSWORD='sync_123456',MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=900;
#開啟同步
START SLAVE;
#查看slave同步狀態
SHOW SLAVE STATUS\G
如果出現以下情況
是mysql從節點正處于連接狀態,等待一會兒即可,直到后續日志列印出同步資訊即可,如果是Yes則不需要等待

同步資訊如下

啟動成功之后如下

測驗同步
1.進入master,創建一個測驗資料庫
docker exec -ti mysql bash
mysql -uroot -p123456
CREATE DATABASE test;

2.進入slave,查看對應的test庫是否同步過來
docker exec -ti slave bash
mysql -uroot -p123456
SHOW DATABASES;

基于docker,使用腳本的方式實作主從
為什么說是使用腳本的方式呢,因為在docker容器里面的mysql,是通過entrypoint.sh來啟動mysql的,如果mysql是第一次啟動,在初始化完成之后,會去加載/docker-entrypoint-initdb.d這個目錄下面的腳本執行,所以我們可以撰寫同步腳本,將其掛載在這個目錄下即可
以下操作都在mysql目錄中執行,我的目錄如下圖

撰寫master用于創建同步賬號的腳本
注意:在執行到這一步之前,請關掉上面啟動的mysql和slave兩個容器,可以執行以下命令
docker rm -f mysql
docker rm -f slave
#創建對應目錄
mkdir -p ./init/{master,slave}
#將master初始化腳本寫入到init/master目錄下
cat > ./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陳述句
CREATE_USER_SQL="CREATE USER '\$MASTER_SYNC_USER'@'\$ALLOW_HOST' IDENTIFIED 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
啟動mysql-master,掛載腳本
創建網卡,保證master和slave都在同一個網段
docker network create --driver=bridge --subnet=10.10.0.0/16 mysql
docker run --name mysql-master -v ${PWD}/init/master:/docker-entrypoint-initdb.d -e MYSQL_ROOT_PASSWORD="123456" -e MASTER_SYNC_USER="sync_root" -e MASTER_SYNC_PASSWORD="sync_123456" -e ADMIN_USER="root" -e ADMIN_PASSWORD="123456" -e ALLOW_HOST="10.10.%.%" -e TZ="Asia/Shanghai" --ip 10.10.10.10 --network mysql -d mysql:8.0.13 --server-id=1 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --log-bin=mysql-bin --sync_binlog=1
撰寫mysql-slave腳本
mkdir -p ./init/slave
cat > ./init/slave/slave.sh <<EOF
#定義連接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
啟動mysql-slave
docker run --name mysql-slave --network mysql -v ${PWD}/init/slave:/docker-entrypoint-initdb.d -e SLAVE_SYNC_USER="sync_root" -e SLAVE_SYNC_PASSWORD="sync_123456" -e MASTER_HOST="10.10.10.10" -e MYSQL_ROOT_PASSWORD="123456" -e ADMIN_USER="root" -e ADMIN_PASSWORD="123456" -d mysql:8.0.13 --server-id=2 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
查看日志,如果出現以下情況,等待一會兒,直到后續日志列印出同步資訊即可
#查看日志
docker logs -f mysql-slave

同步資訊如下

開啟同步成功如下圖

測驗同步資料
1.進入mysql-master,創建一個資料庫
docker exec -ti mysql-master bash
mysql -uroot -p123456
CREATE DATABASE `test-master`;
SHOW DATABASES;

2.進入mysql-slave,查看同步情況
docker exec -ti mysql-slave bash
mysql -uroot -p123456
SHOW DATABASES;

使用docker-compose,實作一鍵部署一主二從
在執行此腳本之前,請洗掉之前創建的mysql-master mysql-slave容器,以及mysql網卡
docker rm -f mysql-master
docker rm -f mysql-slave
docker network rm mysql
撰寫docker-compose.yml檔案
version: '3'
services:
mysql-master:
image: mysql:8.0.13
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: "10.10.%.%" #允許同步賬號的host地址
TZ: "Asia/Shanghai" #解決時區問題
networks:
mysql:
ipv4_address: "10.10.10.10" #固定ip,因為從庫在連接master的時候,需要設定host
volumes:
- ./init/master:/docker-entrypoint-initdb.d #掛載master腳本
command:
- "--server-id=1"
- "--character-set-server=utf8mb4"
- "--collation-server=utf8mb4_unicode_ci"
- "--log-bin=mysql-bin"
- "--sync_binlog=1"
mysql-slave1:
image: mysql:8.0.13
container_name: mysql-slave1
environment:
MYSQL_ROOT_PASSWORD: "123456"
SLAVE_SYNC_USER: "sync_admin" #用于同步的賬號,由master創建
SLAVE_SYNC_PASSWORD: "123456"
ADMIN_USER: "root"
ADMIN_PASSWORD: "123456"
MASTER_HOST: "10.10.10.10" #master地址,開啟主從同步需要連接master
TZ: "Asia/Shanghai" #設定時區
networks:
- mysql
volumes:
- ./init/slave:/docker-entrypoint-initdb.d #掛載slave腳本
command:
- "--server-id=2"
- "--character-set-server=utf8mb4"
- "--collation-server=utf8mb4_unicode_ci"
mysql-slave2:
image: mysql:8.0.13
container_name: mysql-slave2
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"
networks:
- mysql
volumes:
- ./init/slave:/docker-entrypoint-initdb.d
command: #這里需要修改server-id,保證每個mysql容器的server-id都不一樣
- "--server-id=3"
- "--character-set-server=utf8mb4"
- "--collation-server=utf8mb4_unicode_ci"
networks:
mysql:
driver: bridge
ipam:
driver: default
config:
- subnet: "10.10.0.0/16"
運行docker-compose.yaml
當前目錄如下

運行情況如下

查看三臺容器的日志
-
mysql-master
docker logs -f mysql-master

-
mysql-slave1
docker logs -f mysql-slave1

-
mysql-slave2
docker logs -f mysql-slave2

測驗資料同步
-
mysql-master
創建資料庫,資料表,并插入測驗資料
docker exec -ti mysql-master bash
mysql -uroot -p123456
CREATE DATABASE `sync-data`;
USE `sync-data`;
CREATE TABLE `sync-data`(
id INT(10) AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20) NOT NULL DEFAULT '' COMMENT '名稱'
) ENGINE=INNODB;
INSERT INTO `sync-data`(`name`) VALUES('zhangsan'),('lisi');

-
mysql-slave1
進入mysql-slave1,查看資料同步情況
docker exec -ti mysql-slave1 bash
mysql -uroot -p123456
SELECT * FROM `sync-data`.`sync-data`;

-
mysql-slave2
進入mysql-slave2,查看資料同步情況
docker exec -ti mysql-slave2 bash
mysql -uroot -p123456
SELECT * FROM `sync-data`.`sync-data`;

加入nginx,實作slave的負載均衡
創建nginx負責均衡的組態檔
這里使用tcp代理,需要開啟nginx的stream支持
-
創建nginx.conf,開啟stream支持
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
-
撰寫mysql.conf
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 10.10.10.20:3306 weight=1;
server 10.10.10.30:3306 weight=1;
}
server {
listen 0.0.0.0:3307;
proxy_pass mysql-slave-cluster;
}
EOF
修改docker-compose.yml
version: '3'
services:
mysql-slave-lb:
image: nginx:alpine
container_name: mysql-slave-lb
ports:
- 3307:3307
volumes:
- ./conf.d/stream:/opt/nginx/stream/conf.d
- ./nginx.conf:/etc/nginx/nginx.conf
networks:
- mysql
depends_on:
- mysql-master
- mysql-slave1
- mysql-slave2
mysql-master:
image: mysql:8.0.13
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: "10.10.%.%" #允許同步賬號的host地址
TZ: "Asia/Shanghai" #解決時區問題
ports:
- 3306:3306
networks:
mysql:
ipv4_address: "10.10.10.10" #固定ip,因為從庫在連接master的時候,需要設定host
volumes:
- ./init/master:/docker-entrypoint-initdb.d #掛載master腳本
command:
- "--server-id=1"
- "--character-set-server=utf8mb4"
- "--collation-server=utf8mb4_unicode_ci"
- "--log-bin=mysql-bin"
- "--sync_binlog=1"
mysql-slave1:
image: mysql:8.0.13
container_name: mysql-slave1
environment:
MYSQL_ROOT_PASSWORD: "123456"
SLAVE_SYNC_USER: "sync_admin" #用于同步的賬號,由master創建
SLAVE_SYNC_PASSWORD: "123456"
ADMIN_USER: "root"
ADMIN_PASSWORD: "123456"
MASTER_HOST: "10.10.10.10" #master地址,開啟主從同步需要連接master
TZ: "Asia/Shanghai" #設定時區
networks:
mysql:
ipv4_address: "10.10.10.20" #固定ip
volumes:
- ./init/slave:/docker-entrypoint-initdb.d #掛載slave腳本
command:
- "--server-id=2"
- "--character-set-server=utf8mb4"
- "--collation-server=utf8mb4_unicode_ci"
mysql-slave2:
image: mysql:8.0.13
container_name: mysql-slave2
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"
networks:
mysql:
ipv4_address: "10.10.10.30" #固定ip
volumes:
- ./init/slave:/docker-entrypoint-initdb.d
command: #這里需要修改server-id,保證每個mysql容器的server-id都不一樣
- "--server-id=3"
- "--character-set-server=utf8mb4"
- "--collation-server=utf8mb4_unicode_ci"
networks:
mysql:
driver: bridge
ipam:
driver: default
config:
- subnet: "10.10.0.0/16"
執行docker-compose
當前目錄如下

# 停掉之前啟動的的容器
docker-compose down
#啟動
docker-compose up -d
確保mysql-slave mysql-slave2的同步狀態都是yes或者Connection,如果不是,請停掉容器,重新啟動
如果是Connection狀態,請等待片刻進入容器登錄mysql重新查詢狀態,直到確認是Yes即可
查詢狀態的命令 show slave status\G

使用navicat連接從庫

在mysql-master中創建測驗資料,并進入navicat查看情況
1.插入資料
docker exec -ti mysql-master bash
mysql -uroot -p123456
CREATE DATABASE `sync-data`;
USE `sync-data`;
CREATE TABLE `sync-data`(
id INT(10) AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20) NOT NULL DEFAULT '' COMMENT '名稱'
) ENGINE=INNODB;
INSERT INTO `sync-data`(`name`) VALUES('zhangsan1'),('lisi1');
2.進入navicat查看資料如下

寫在最后
這里講述了如何手動搭建mysql主從,如何通過腳本一鍵的方式搭建主從,然后這里可以告訴大家,在使用腳本的方式搭建主從,有很多擴展性,如實作主主雙寫同步,多主多從集群方式,還可以加入檢查腳本,實時檢測同步情況,實作重連等等
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/276741.html
標籤:其他
下一篇:linux安全之seccomp
