分享一下基于Mysql主从复制+读写分离的方案。
主从复制:Mysql Master-Slave bin-log。
读写分离:Mariadb MaxScale Proxy。
搭建环境是基于Docker,Docker Compose。

1. 创建目录,1台主master,2台从slave。

  1. mkdir -p mysql/master/conf
  2. mkdir -p mysql/master/data
  3. mkdir -p mysql/master/logs
  4. mkdir -p mysql/slave1/conf
  5. mkdir -p mysql/slave1/data
  6. mkdir -p mysql/slave1/logs
  7. mkdir -p mysql/slave2/conf
  8. mkdir -p mysql/slave2/data
  9. mkdir -p mysql/slave2/logs
  10. mkdir -p mysql/maxscale

mysql目录结构如下:

  1. .
  2. ├── docker-compose.yml
  3. ├── master
  4. ├── conf
  5. └── config-file.cnf
  6. ├── data
  7. └── logs
  8. ├── maxscale
  9. └── my-maxscale.cnf
  10. ├── slave1
  11. ├── conf
  12. └── config-file.cnf
  13. ├── data
  14. └── logs
  15. └── slave2
  16. ├── conf
  17. └── config-file.cnf
  18. ├── data
  19. └── logs

2. 创建Mysql的配置文件 config-file.cnf 并放入conf文件夹。

2.1 Master的 config-file.cnf 参考配置

  1. [client]
  2. port = 3306
  3. default-character-set = utf8mb4
  4. [mysqld]
  5. port = 3306
  6. default-authentication-plugin = mysql_native_password
  7. character-set-server = utf8mb4
  8. collation-server = utf8mb4_general_ci
  9. explicit_defaults_for_timestamp = true
  10. lower_case_table_names = 1
  11. max_allowed_packet = 128M
  12. # Replication Master Server (default)
  13. # binary logging is required for replication
  14. log-bin = bin-log
  15. log-bin-index = bin-log.index
  16. sync_binlog = 1
  17. # binary logging format - mixed recommended
  18. binlog_format = mixed
  19. expire_logs_days = 3
  20. # required unique id between 1 and 2^32 - 1
  21. # defaults to 1 if master-host is not set
  22. # but will not function as a master if omitted
  23. server-id = 100
  24. sql-mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
  25. [mysqldump]
  26. quick
  27. max_allowed_packet = 128M
  28. [mysql]
  29. no-auto-rehash
  30. # Remove the next comment character if you are not familiar with SQL
  31. #safe-updates
  32. default-character-set=utf8
  33. [myisamchk]
  34. key_buffer_size = 20M
  35. sort_buffer_size = 20M
  36. read_buffer = 2M
  37. write_buffer = 2M
  38. [mysqlhotcopy]
  39. interactive-timeout

2.2 Slave的 config-file.cnf 参考配置

  1. [client]
  2. port = 3307
  3. default-character-set = utf8mb4
  4. [mysqld]
  5. port = 3307
  6. default-authentication-plugin = mysql_native_password
  7. character-set-server = utf8mb4
  8. collation-server = utf8mb4_general_ci
  9. explicit_defaults_for_timestamp = true
  10. lower_case_table_names = 1
  11. max_allowed_packet = 128M
  12. # Replication Master Server (default)
  13. # binary logging is required for replication
  14. log-bin = bin-log
  15. log-bin-index = bin-log.index
  16. # 可以不配置中继日志,当服务器以从模式运行时,将会自动开启
  17. relay-log = relay-log
  18. # 指定 relay 日志的索引文件。
  19. relay-log-index = relay-log.index
  20. read_only = 1
  21. # binary logging format - mixed recommended
  22. binlog_format = mixed
  23. #
  24. expire_logs_days = 3
  25. # required unique id between 1 and 2^32 - 1
  26. # defaults to 1 if master-host is not set
  27. # but will not function as a master if omitted
  28. server-id = 101
  29. sql-mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
  30. [mysqldump]
  31. quick
  32. max_allowed_packet = 128M
  33. [mysql]
  34. no-auto-rehash
  35. # Remove the next comment character if you are not familiar with SQL
  36. #safe-updates
  37. default-character-set=utf8
  38. [myisamchk]
  39. key_buffer_size = 20M
  40. sort_buffer_size = 20M
  41. read_buffer = 2M
  42. write_buffer = 2M
  43. [mysqlhotcopy]
  44. interactive-timeout

3. 创建MaxScale的配置文件 my-maxscale.cnf 并放入maxscale文件夹。

官方配置参考点这里。推荐一篇讲解MaxScale的文章。

  1. [server1]
  2. type=server
  3. # Replace address and port of yours, and the same as below.
  4. address=192.168.3.77
  5. port=3306
  6. protocol=MariaDBBackend
  7. [server2]
  8. type=server
  9. address=192.168.3.77
  10. port=3307
  11. protocol=MariaDBBackend
  12. [server3]
  13. type=server
  14. address=192.168.3.77
  15. port=3308
  16. protocol=MariaDBBackend
  17. [MariaDB-Monitor]
  18. type=monitor
  19. module=mariadbmon
  20. servers=server1,server2,server3
  21. # user and password should be created in all above mysql servers, and be authorized.
  22. user=maxscalemon
  23. password=111111
  24. failcount=3
  25. backend_connect_timeout=3
  26. backend_write_timeout=3
  27. backend_read_timeout=3
  28. auto_failover=true
  29. auto_rejoin=true
  30. enforce_read_only_slaves=1
  31. [Read-Write-Service]
  32. type=service
  33. router=readwritesplit
  34. servers=server1,server2,server3
  35. # user and password should be created in all above mysql servers, and be authorized.
  36. user=maxscalerouter
  37. password=111111
  38. master_failure_mode=fail_on_write
  39. # Solve the problem of invalid recursive query
  40. use_sql_variables_in=master
  41. [Read-Write-Listener]
  42. type=listener
  43. service=Read-Write-Service
  44. protocol=MySQLClient
  45. # Solve ipv6 problem
  46. address=0.0.0.0
  47. port=4006

4. 创建docker-compose.yml文件并放在根目录。

MaxScale的官方配置官方文档参考。

  1. version: '3.8'
  2. services:
  3. mysql-master:
  4. container_name: mysql-master
  5. image: mysql:5.7
  6. # restart: always
  7. environment:
  8. TZ: Asia/Shanghai
  9. MYSQL_ROOT_PASSWORD: 111111
  10. ports:
  11. - 3306:3306
  12. volumes:
  13. - ./master/data:/var/lib/mysql
  14. - ./master/logs:/var/log/mysql
  15. - ./master/conf:/etc/mysql/conf.d
  16. mysql-slave1:
  17. container_name: mysql-slave1
  18. image: mysql:5.7
  19. # restart: always
  20. environment:
  21. TZ: Asia/Shanghai
  22. MYSQL_ROOT_PASSWORD: 111111
  23. ports:
  24. - 3307:3307
  25. volumes:
  26. - ./slave1/data:/var/lib/mysql
  27. - ./slave1/logs:/var/log/mysql
  28. - ./slave1/conf:/etc/mysql/conf.d
  29. depends_on:
  30. - mysql-master
  31. mysql-slave2:
  32. container_name: mysql-slave2
  33. image: mysql:5.7
  34. # restart: always
  35. environment:
  36. TZ: Asia/Shanghai
  37. MYSQL_ROOT_PASSWORD: 111111
  38. ports:
  39. - 3308:3308
  40. volumes:
  41. - ./slave2/data:/var/lib/mysql
  42. - ./slave2/logs:/var/log/mysql
  43. - ./slave2/conf:/etc/mysql/conf.d
  44. depends_on:
  45. - mysql-master
  46. maxscale:
  47. container_name: mysql-maxscale
  48. image: mariadb/maxscale:2.5
  49. depends_on:
  50. - mysql-master
  51. - mysql-slave1
  52. - mysql-slave2
  53. volumes:
  54. - ./maxscale:/etc/maxscale.cnf.d
  55. ports:
  56. - 4006:4006 # readwrite port
  57. # - '4008:4008' # readonly port
  58. - 8989:8989 # REST API port

5. 以上配置都创建好后,开始实操。

5.1 注释掉docker-compose.yml的maxscale节点。下面这段。

因为MaxScale的读写分离依赖主从复制的Mysql集群,并且依赖Mysql的授权用户。

  1. maxscale:
  2. container_name: mysql-maxscale
  3. image: mariadb/maxscale:2.5
  4. depends_on:
  5. - mysql-master
  6. - mysql-slave1
  7. - mysql-slave2
  8. volumes:
  9. - ./maxscale:/etc/maxscale.cnf.d
  10. ports:
  11. - 4006:4006 # readwrite port
  12. # - '4008:4008' # readonly port
  13. - 8989:8989 # REST API port

5.2 单独启动Mysql。

  1. docker-compose up

启动好后如下图。
image.png

5.3 配置Mysql主从复制。

5.3.1 连接Master主库。

5.3.1.1创建从库用户。

  1. CREATE USER 'slave-user'@'%' IDENTIFIED BY 'slave-password';
  2. GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave-user'@'%';

5.3.1.2 查看主库状态。

  1. SHOW MASTER STATUS;

File和Position要记下来,后面配置从库使用。
image.png

5.3.2 连接Slave从库。

5.3.2.1 配置从库连接主库。

  1. CHANGE MASTER TO
  2. master_host = '192.168.3.77', -- Master主库的ip
  3. master_port = 3306, -- Master主库的port
  4. master_user = 'slave', -- Master主库创建的用于同步数据的账号
  5. master_password = '111111', -- Master主库创建的用于同步数据的密码
  6. master_log_file = 'mysql-master-bin.000003', -- Master主库的File
  7. master_log_pos = 831, -- Master主库的Position
  8. master_connect_retry = 30;

5.3.2.2 开启/停止/查看从库。

  1. START SLAVE; -- 开启复制
  2. STOP SLAVE; -- 停止复制
  3. RESET SLAVE; -- 重置复制
  4. SHOW SLAVE STATUS; -- 查看从库状态

查看从库状态并确认Slave_IO_Running和Slave_SQL_Running是Yes。
image.png
至此,Mysql主从复制完成。

5.3.3 继续创建Maxscale使用监控账号和路由账号,顺便测试一下主从复制是否已成功。

5.3.3.1 创建监控用户并授权。

确认创建的用户名和密码对应 my-maxscale.cnf 中 [MariaDB-Monitor] 节点下的user和password。

  1. CREATE USER 'maxscalemon'@'%' IDENTIFIED BY '111111';
  2. GRANT REPLICATION CLIENT on *.* to 'maxscalemon'@'%';
  3. FLUSH PRIVILEGES;

5.3.3.2 创建路由用户并授权。

确认创建的用户名和密码对应 my-maxscale.cnf 中 [Read-Write-Service] 节点下的user和password。

  1. CREATE USER 'maxscalerouter'@'%' IDENTIFIED BY '111111';
  2. GRANT SELECT ON mysql.* TO maxscalerouter@'%';
  3. GRANT SHOW DATABASES ON *.* TO maxscalerouter@'%';
  4. FLUSH PRIVILEGES;

5.3.4 分别主库和从库,查看 监控用户 和 路由用户 是否已创建完成并已从主库同步到从库中。

  1. SELECT `User`, `Host` FROM `user` WHERE `User` LIKE 'maxscale%';

5.4 配置读写分离。

停止Container,打开先前注释掉docker-compose.yml的maxscale节点,重新启动,启动好后如下图。
image.png

5.5 测试读写分离。

5.5.1 新建1个Mysql账号并授权。

  1. CREATE USER 'rwtest' @'%' IDENTIFIED BY '111111';
  2. 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
image.png

6. Spring + Druid 集成。

数据源配置与单机版mysql相同,无缝对接。

6.1 pom.xml

  1. <properties>
  2. <mysql.version>8.0.27</mysql.version>
  3. <druid.version>1.1.24</druid.version>
  4. </properties>
  5. <dependencies>
  6. <dependency>
  7. <groupId>mysql</groupId>
  8. <artifactId>mysql-connector-java</artifactId>
  9. <version>${mysql.version}</version>
  10. <scope>runtime</scope>
  11. </dependency>
  12. <dependency>
  13. <groupId>com.alibaba</groupId>
  14. <artifactId>druid-spring-boot-starter</artifactId>
  15. <version>${druid.version}</version>
  16. </dependency>
  17. </dependencies>

6.2 application.properties

  1. spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
  2. spring.datasource.druid.url=jdbc:mysql://192.168.3.77:4006/your-database?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
  3. spring.datasource.druid.username=beauty
  4. spring.datasource.druid.password=111111