分享一下基于Mysql主从复制+读写分离的方案。
主从复制:Mysql Master-Slave bin-log。
读写分离:Mariadb MaxScale Proxy。
搭建环境是基于Docker,Docker Compose。
1. 创建目录,1台主master,2台从slave。
mkdir -p mysql/master/confmkdir -p mysql/master/datamkdir -p mysql/master/logsmkdir -p mysql/slave1/confmkdir -p mysql/slave1/datamkdir -p mysql/slave1/logsmkdir -p mysql/slave2/confmkdir -p mysql/slave2/datamkdir -p mysql/slave2/logsmkdir -p mysql/maxscale
mysql目录结构如下:
.├── docker-compose.yml├── master│ ├── conf│ │ └── config-file.cnf│ ├── data│ └── logs├── maxscale│ └── my-maxscale.cnf├── slave1│ ├── conf│ │ └── config-file.cnf│ ├── data│ └── logs└── slave2├── conf│ └── config-file.cnf├── data└── logs
2. 创建Mysql的配置文件 config-file.cnf 并放入conf文件夹。
2.1 Master的 config-file.cnf 参考配置
[client]port = 3306default-character-set = utf8mb4[mysqld]port = 3306default-authentication-plugin = mysql_native_passwordcharacter-set-server = utf8mb4collation-server = utf8mb4_general_ciexplicit_defaults_for_timestamp = truelower_case_table_names = 1max_allowed_packet = 128M# Replication Master Server (default)# binary logging is required for replicationlog-bin = bin-loglog-bin-index = bin-log.indexsync_binlog = 1# binary logging format - mixed recommendedbinlog_format = mixedexpire_logs_days = 3# required unique id between 1 and 2^32 - 1# defaults to 1 if master-host is not set# but will not function as a master if omittedserver-id = 100sql-mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION[mysqldump]quickmax_allowed_packet = 128M[mysql]no-auto-rehash# Remove the next comment character if you are not familiar with SQL#safe-updatesdefault-character-set=utf8[myisamchk]key_buffer_size = 20Msort_buffer_size = 20Mread_buffer = 2Mwrite_buffer = 2M[mysqlhotcopy]interactive-timeout
2.2 Slave的 config-file.cnf 参考配置
[client]port = 3307default-character-set = utf8mb4[mysqld]port = 3307default-authentication-plugin = mysql_native_passwordcharacter-set-server = utf8mb4collation-server = utf8mb4_general_ciexplicit_defaults_for_timestamp = truelower_case_table_names = 1max_allowed_packet = 128M# Replication Master Server (default)# binary logging is required for replicationlog-bin = bin-loglog-bin-index = bin-log.index# 可以不配置中继日志,当服务器以从模式运行时,将会自动开启relay-log = relay-log# 指定 relay 日志的索引文件。relay-log-index = relay-log.indexread_only = 1# binary logging format - mixed recommendedbinlog_format = mixed#expire_logs_days = 3# required unique id between 1 and 2^32 - 1# defaults to 1 if master-host is not set# but will not function as a master if omittedserver-id = 101sql-mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION[mysqldump]quickmax_allowed_packet = 128M[mysql]no-auto-rehash# Remove the next comment character if you are not familiar with SQL#safe-updatesdefault-character-set=utf8[myisamchk]key_buffer_size = 20Msort_buffer_size = 20Mread_buffer = 2Mwrite_buffer = 2M[mysqlhotcopy]interactive-timeout
3. 创建MaxScale的配置文件 my-maxscale.cnf 并放入maxscale文件夹。
[server1]type=server# Replace address and port of yours, and the same as below.address=192.168.3.77port=3306protocol=MariaDBBackend[server2]type=serveraddress=192.168.3.77port=3307protocol=MariaDBBackend[server3]type=serveraddress=192.168.3.77port=3308protocol=MariaDBBackend[MariaDB-Monitor]type=monitormodule=mariadbmonservers=server1,server2,server3# user and password should be created in all above mysql servers, and be authorized.user=maxscalemonpassword=111111failcount=3backend_connect_timeout=3backend_write_timeout=3backend_read_timeout=3auto_failover=trueauto_rejoin=trueenforce_read_only_slaves=1[Read-Write-Service]type=servicerouter=readwritesplitservers=server1,server2,server3# user and password should be created in all above mysql servers, and be authorized.user=maxscalerouterpassword=111111master_failure_mode=fail_on_write# Solve the problem of invalid recursive queryuse_sql_variables_in=master[Read-Write-Listener]type=listenerservice=Read-Write-Serviceprotocol=MySQLClient# Solve ipv6 problemaddress=0.0.0.0port=4006
4. 创建docker-compose.yml文件并放在根目录。
version: '3.8'services:mysql-master:container_name: mysql-masterimage: mysql:5.7# restart: alwaysenvironment:TZ: Asia/ShanghaiMYSQL_ROOT_PASSWORD: 111111ports:- 3306:3306volumes:- ./master/data:/var/lib/mysql- ./master/logs:/var/log/mysql- ./master/conf:/etc/mysql/conf.dmysql-slave1:container_name: mysql-slave1image: mysql:5.7# restart: alwaysenvironment:TZ: Asia/ShanghaiMYSQL_ROOT_PASSWORD: 111111ports:- 3307:3307volumes:- ./slave1/data:/var/lib/mysql- ./slave1/logs:/var/log/mysql- ./slave1/conf:/etc/mysql/conf.ddepends_on:- mysql-mastermysql-slave2:container_name: mysql-slave2image: mysql:5.7# restart: alwaysenvironment:TZ: Asia/ShanghaiMYSQL_ROOT_PASSWORD: 111111ports:- 3308:3308volumes:- ./slave2/data:/var/lib/mysql- ./slave2/logs:/var/log/mysql- ./slave2/conf:/etc/mysql/conf.ddepends_on:- mysql-mastermaxscale:container_name: mysql-maxscaleimage: mariadb/maxscale:2.5depends_on:- mysql-master- mysql-slave1- mysql-slave2volumes:- ./maxscale:/etc/maxscale.cnf.dports:- 4006:4006 # readwrite port# - '4008:4008' # readonly port- 8989:8989 # REST API port
5. 以上配置都创建好后,开始实操。
5.1 注释掉docker-compose.yml的maxscale节点。下面这段。
因为MaxScale的读写分离依赖主从复制的Mysql集群,并且依赖Mysql的授权用户。
maxscale:container_name: mysql-maxscaleimage: mariadb/maxscale:2.5depends_on:- mysql-master- mysql-slave1- mysql-slave2volumes:- ./maxscale:/etc/maxscale.cnf.dports:- 4006:4006 # readwrite port# - '4008:4008' # readonly port- 8989:8989 # REST API port
5.2 单独启动Mysql。
docker-compose up
5.3 配置Mysql主从复制。
5.3.1 连接Master主库。
5.3.1.1创建从库用户。
CREATE USER 'slave-user'@'%' IDENTIFIED BY 'slave-password';GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave-user'@'%';
5.3.1.2 查看主库状态。
SHOW MASTER STATUS;
5.3.2 连接Slave从库。
5.3.2.1 配置从库连接主库。
CHANGE MASTER TOmaster_host = '192.168.3.77', -- Master主库的ipmaster_port = 3306, -- Master主库的portmaster_user = 'slave', -- 在Master主库创建的用于同步数据的账号master_password = '111111', -- 在Master主库创建的用于同步数据的密码master_log_file = 'mysql-master-bin.000003', -- Master主库的Filemaster_log_pos = 831, -- Master主库的Positionmaster_connect_retry = 30;
5.3.2.2 开启/停止/查看从库。
START SLAVE; -- 开启复制STOP SLAVE; -- 停止复制RESET SLAVE; -- 重置复制SHOW SLAVE STATUS; -- 查看从库状态
查看从库状态并确认Slave_IO_Running和Slave_SQL_Running是Yes。
至此,Mysql主从复制完成。
5.3.3 继续创建Maxscale使用监控账号和路由账号,顺便测试一下主从复制是否已成功。
5.3.3.1 创建监控用户并授权。
确认创建的用户名和密码对应 my-maxscale.cnf 中 [MariaDB-Monitor] 节点下的user和password。
CREATE USER 'maxscalemon'@'%' IDENTIFIED BY '111111';GRANT REPLICATION CLIENT on *.* to 'maxscalemon'@'%';FLUSH PRIVILEGES;
5.3.3.2 创建路由用户并授权。
确认创建的用户名和密码对应 my-maxscale.cnf 中 [Read-Write-Service] 节点下的user和password。
CREATE USER 'maxscalerouter'@'%' IDENTIFIED BY '111111';GRANT SELECT ON mysql.* TO maxscalerouter@'%';GRANT SHOW DATABASES ON *.* TO maxscalerouter@'%';FLUSH PRIVILEGES;
5.3.4 分别主库和从库,查看 监控用户 和 路由用户 是否已创建完成并已从主库同步到从库中。
SELECT `User`, `Host` FROM `user` WHERE `User` LIKE 'maxscale%';
5.4 配置读写分离。
停止Container,打开先前注释掉docker-compose.yml的maxscale节点,重新启动,启动好后如下图。
5.5 测试读写分离。
5.5.1 新建1个Mysql账号并授权。
CREATE USER 'rwtest' @'%' IDENTIFIED BY '111111';GRANT ALL PRIVILEGES ON *.* TO 'rwtest' @'%';
5.5.2 连接MaxScale读写分离端口4006。连接成功后建表并执行增删改查语句。
5.5.3 MaxScale2.5提供了可视化页面来查看Mysql服务端的运行状态。
打开浏览器访问:http://192.168.3.77:8989/
默认账号密码:admin / mariadb
6. Spring + Druid 集成。
6.1 pom.xml
<properties><mysql.version>8.0.27</mysql.version><druid.version>1.1.24</druid.version></properties><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version><scope>runtime</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>${druid.version}</version></dependency></dependencies>
6.2 application.properties
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.druid.url=jdbc:mysql://192.168.3.77:4006/your-database?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=falsespring.datasource.druid.username=beautyspring.datasource.druid.password=111111
