MySQL读写分离那些事,用Docker轻轻松松搞定

数据库 MySQL
根据MySQL的官方文档介绍,MySQL支持读写分离的集群配置,并且MySQL提供两种类型的读写分离数据复制类型;一种是二进制日志文件方式的数据复制,另一种是Global Transaction Identifiers (GTIDs)。

 一个应用系统是否高可用,整个系统的效率是否满足预期,往往受到多方面的制约因素,例如:运行环境,网络环境以及数据的吞吐量等;作为一般的大型应用系统来说,我们想要提升整个系统的效率,我们大多数情况下会从我们的后端数据库做优化,从而提高我们整个系统的数据吞吐量,如果我们后端采用的是关系型数据,我们可能会想到两种解决方案,一种是更换非关系型数据库,这种方案代价比较昂贵,它会涉及到数据的迁移,以及程序代码的修改;另一种是通过数据库集群的方式,来横向和纵向扩展我们的数据库,这种方案容易实现并且程序代码修改量比较小;

[[283981]]

根据MySQL的官方文档介绍,MySQL支持读写分离的集群配置,并且MySQL提供两种类型的读写分离数据复制类型;一种是二进制日志文件方式的数据复制,另一种是Global Transaction Identifiers (GTIDs)。

下面我们通过一个小实验来看看MySQL数据基于二进制日志数据复制方式的主从集群是如何实现的。

OS环境:CentOS7

软件环境:Docker(最新版),MySQL:latest镜像

我们通过Docker容器快速的构建两个MySQL数据库服务器

docker pull mysql 
[root@dev01 ~]# docker images 
REPOSITORY TAG IMAGE ID CREATED SIZE 
mysql latest 62a9f311b99c 4 weeks ago 445MB 
  • 1.
  • 2.
  • 3.
  • 4.

可以看到我们已经拉取到最新的MySQL Docker容器,为了在本地环境中启动两个不同的MySQL Docker容器,我们需要通过修改容器的配置文件的方式来改变MySQL的配置;

首先,我们修改MySQL Master(主数据库)的容器配置文件:

一,创建Master数据库的配置文件

vi master.cnf 
[mysqld] 
# master server id 
server-id = 1 
 
# bin log 
log_bin = mysql-master-bin 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • server-id,在MySQL集群数据库中,这个参数必须唯一
  • log_bin,MySQL采用二进制日志文件复制的文件名

二,将该配置文件拷贝到MySQL Docker容器中

docker run --name mysql -e MYSQL_ROOT_PASSWORD=root -d mysql 
docker cp master.cnf fdb98bbd52b6:/etc/mysql/conf.d 
  • 1.
  • 2.

三,提交修改后的Docker容器

docker commit -m "add master configure file" fdb98bbd52b6 mysql:master 
[root@dev01 ~]# docker images 
REPOSITORY TAG IMAGE ID CREATED SIZE 
mysql master 345465966cb5 3 hours ago 445MB 
  • 1.
  • 2.
  • 3.
  • 4.
  • commit -m是修改容器后提交的信息,类似Git提交;
  • fdb98bbd52b6是刚才修改的容器;
  • mysql:master是我们为修改后的容器打上tag标签master

接下来我们修改MySQL Slave(从数据库)的容器配置文件

一,创建Slave数据库的配置文件

vi slave.cnf 
[mysqld] 
# slave server id 
server-id = 2 
 
# bin log 
log_bin = mysql-slave-bin 
relay_log = mysql-relay-bin 
log_slave_updates = 1 
read_only = 1 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • server-id为从数据库的ID,该参数在MySQL集群中必须保持唯一性;
  • log_bin如果slave为其它slave的master,必须设置bin_log,在这里我们暂时开启;
  • relay_log配置中继日志
  • log_slave_updates表示slave将复制事件写进自己的二进制日志(后面会看到它的用处);
  • read_only尽量使用read_only,它防止改变数据(除了特殊的线程);

二,将配置文件拷贝到容器中

docker run --name mysql -e MYSQL_ROOT_PASSWORD=root -d mysql 
docker cp slave.cnf 8ee82abb2e91:/etc/mysql/conf.d 
  • 1.
  • 2.

三,提交修改后的Docker容器

docker commit -m "add slave configure file" 8ee82abb2e91 mysql:slave 
[root@dev01 ~]# docker images 
REPOSITORY TAG IMAGE ID CREATED SIZE 
mysql slave 3a53cd39ee45 4 hours ago 445MB 
  • 1.
  • 2.
  • 3.
  • 4.

到此,所需要的两个MySQL容器已经修改完毕,并且保存在我们本地的容器仓库中,接下来我们开始启动刚才修改的两个容器进行后续的配置

一,启动Master数据库

docker run --name master -e MYSQL_ROOT_PASSWORD=root -d mysql:master 
  • 1.
  • --name master是我们为启动的容器名;
  • mysql:master是我们刚才修改后并且提交到本地的Docker镜像
  • 默认数据库root的密码设置为root

二,启动Slave数据库

docker run --link master:master --name slave -e MYSQL_ROOT_PASSWORD=root -d mysql:slave 
  • 1.
  • 为了master容器与slave容器的网络互通,我们添加了--line选项来连接到我们刚才启动的名为master容器;
  • --name slave是我们为启动的容器名;
  • mysql:slave是我们刚才修改后并且提交到本地的Docker镜像;
  • 默认数据库root的密码设置为root

三,进入master容器中通过mysql命令进入数据库

docker exec -it master /bin/bash 
mysql -u root -proot 
  • 1.
  • 2.

四,在master数据库中创建用于复制数据的账号,并且给该账号相应的权限

create user 'repl'@'%' identified by 'repl-pwd'
grant replication slave on *.* to 'repl'@'%'
flush privileges
  • 1.
  • 2.
  • 3.

五,查看master数据库的状态

mysql> show master status; 
+-------------------------+----------+--------------+------------------+-------------------+ 
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | 
+-------------------------+----------+--------------+------------------+-------------------+ 
| mysql-master-bin.000003 | 2743 | | | | 
+-------------------------+----------+--------------+------------------+-------------------+ 
1 row in set (0.00 sec) 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

六,进入slave容器中通过mysql命令进入数据库

docker exec -it slave /bin/bash 
mysql -u root -proot 
  • 1.
  • 2.

七,配置slave,将master数据库指向刚才配置好的master数据库节点,并且启动slave

change master to master_host='master', master_user='repl', master_password='repl-pwd', master_log_file='mysql-master-bin.000003', master_log_pos=0; 
start slave; 
  • 1.
  • 2.

八,查看slave数据库状态

mysql> show slave status\G 
*************************** 1. row *************************** 
 Slave_IO_State: 
 Master_Host: master 
 Master_User: repl 
 Master_Port: 3306 
 Connect_Retry: 60 
 Master_Log_File: mysql-master-bin.000003 
 Read_Master_Log_Pos: 4 
 Relay_Log_File: mysql-relay-bin.000001 
 Relay_Log_Pos: 4 
 Relay_Master_Log_File: mysql-master-bin.000003 
 Slave_IO_Running: No 
 Slave_SQL_Running: No 
 Replicate_Do_DB: 
 Replicate_Ignore_DB: 
 Replicate_Do_Table: 
 Replicate_Ignore_Table: 
 Replicate_Wild_Do_Table: 
 Replicate_Wild_Ignore_Table: 
 Last_Errno: 0 
 Last_Error: 
 Skip_Counter: 0 
 Exec_Master_Log_Pos: 4 
 Relay_Log_Space: 155 
 Until_Condition: None 
 Until_Log_File: 
 Until_Log_Pos: 0 
 Master_SSL_Allowed: No 
 Master_SSL_CA_File: 
 Master_SSL_CA_Path: 
 Master_SSL_Cert: 
 Master_SSL_Cipher: 
 Master_SSL_Key: 
 Seconds_Behind_Master: NULL 
Master_SSL_Verify_Server_Cert: No 
 Last_IO_Errno: 2061 
 Last_IO_Error: error connecting to master 'repl@master:3306' - retry-time: 60 retries: 1 message: Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection
 Last_SQL_Errno: 0 
 Last_SQL_Error: 
 Replicate_Ignore_Server_Ids: 
 Master_Server_Id: 0 
 Master_UUID: 
 Master_Info_File: mysql.slave_master_info 
 SQL_Delay: 0 
 SQL_Remaining_Delay: NULL 
 Slave_SQL_Running_State: 
 Master_Retry_Count: 86400 
 Master_Bind: 
 Last_IO_Error_Timestamp: 190912 06:06:14 
 Last_SQL_Error_Timestamp: 
 Master_SSL_Crl: 
 Master_SSL_Crlpath: 
 Retrieved_Gtid_Set: 
 Executed_Gtid_Set: 
 Auto_Position: 0 
 Replicate_Rewrite_DB: 
 Channel_Name: 
 Master_TLS_Version: 
 Master_public_key_path: 
 Get_master_public_key: 0 
 Network_Namespace: 
1 row in set (0.00 sec) 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.

由于最新版的MySQL为了提升安全性更改了密码校验插件,在这里我们还是采用之前的密码校验插件,我们在master数据库上用如下的命令来修改刚才在master数据库创建的用户

alter user 'repl'@'%' identified by 'repl-pwd' password expire never; 
alter user 'repl'@'%' identified with mysql_native_password by 'repl-pwd'
flush privileges
  • 1.
  • 2.
  • 3.

九,再次查看slave状态

mysql> show slave status\G 
*************************** 1. row *************************** 
 Slave_IO_State: Waiting for master to send event 
 Master_Host: master 
 Master_User: repl 
 Master_Port: 3306 
 Connect_Retry: 60 
 Master_Log_File: mysql-master-bin.000003 
 Read_Master_Log_Pos: 2743 
 Relay_Log_File: mysql-relay-bin.000002 
 Relay_Log_Pos: 2971 
 Relay_Master_Log_File: mysql-master-bin.000003 
 Slave_IO_Running: Yes 
 Slave_SQL_Running: Yes 
 Replicate_Do_DB: 
 Replicate_Ignore_DB: 
 Replicate_Do_Table: 
 Replicate_Ignore_Table: 
 Replicate_Wild_Do_Table: 
 Replicate_Wild_Ignore_Table: 
 Last_Errno: 0 
 Last_Error: 
 Skip_Counter: 0 
 Exec_Master_Log_Pos: 2743 
 Relay_Log_Space: 3179 
 Until_Condition: None 
 Until_Log_File: 
 Until_Log_Pos: 0 
 Master_SSL_Allowed: No 
 Master_SSL_CA_File: 
 Master_SSL_CA_Path: 
 Master_SSL_Cert: 
 Master_SSL_Cipher: 
 Master_SSL_Key: 
 Seconds_Behind_Master: 0 
Master_SSL_Verify_Server_Cert: No 
 Last_IO_Errno: 0 
 Last_IO_Error: 
 Last_SQL_Errno: 0 
 Last_SQL_Error: 
 Replicate_Ignore_Server_Ids: 
 Master_Server_Id: 1 
 Master_UUID: f6e8062e-d521-11e9-9009-0242ac110008 
 Master_Info_File: mysql.slave_master_info 
 SQL_Delay: 0 
 SQL_Remaining_Delay: NULL 
 Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates 
 Master_Retry_Count: 86400 
 Master_Bind: 
 Last_IO_Error_Timestamp: 
 Last_SQL_Error_Timestamp: 
 Master_SSL_Crl: 
 Master_SSL_Crlpath: 
 Retrieved_Gtid_Set: 
 Executed_Gtid_Set: 
 Auto_Position: 0 
 Replicate_Rewrite_DB: 
 Channel_Name: 
 Master_TLS_Version: 
 Master_public_key_path: 
 Get_master_public_key: 0 
 Network_Namespace: 
1 row in set (0.00 sec) 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.

我们主要查看Slave_IO_Running和Slave_SQL_Running,表示我们的slave数据库节点已经成功的连接到了我们的master数据库节点。

十,验证,我们在master数据库节点上创建一个空的数据库

mysql> create database data; 
Query OK, 1 row affected (0.10 sec) 
 
mysql> show databases; 
+--------------------+ 
Database | 
+--------------------+ 
| data | 
| information_schema | 
| mysql | 
| performance_schema | 
| sys | 
+--------------------+ 
rows in set (0.01 sec) 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

十一,验证slave,查看刚才在master数据库节点上创建的数据库是否同步到slave数据节点

mysql> show databases; 
+--------------------+ 
Database | 
+--------------------+ 
| data | 
| information_schema | 
| mysql | 
| performance_schema | 
| sys | 
+--------------------+ 
rows in set (0.01 sec) 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

可以看到,我们刚才在master数据库节点上创建的数据库已经同步到我们的slave数据库节点,master和slave的数据库数据已经保持一致。

以上实验我们选取了两个数据库(一主一从)的方式,在实际的应用中我们会根据我们的应用场景,slave数据库节点也有可能被选择作为主数据库,这个时候slave数据库节点就有可能是1到N个。

参考:

https://dev.mysql.com/doc/refman/5.7/en/replication.html

责任编辑:武晓燕 来源: 今日头条
相关推荐

2009-09-15 16:26:46

Linq排序

2010-01-14 16:10:21

C++开发

2010-01-15 10:14:21

C++ Builder

2010-08-30 09:27:20

2010-03-01 17:32:21

Python 测试模块

2010-03-03 18:13:23

Android组成框架

2011-04-28 15:41:02

打印机卡纸

2010-01-26 14:53:43

C++

2017-10-27 12:00:28

MySQL数据库优化

2009-06-10 17:58:41

2010-01-20 10:31:18

C++编程技术

2010-01-18 11:20:58

C++语言

2010-01-20 18:17:55

C++异常问题

2009-11-09 15:41:14

WCF安全性

2009-11-10 15:44:17

VB.NET常量

2015-09-22 10:31:11

2009-02-20 13:39:01

2009-11-11 09:31:44

ADO.NET事务处理

2012-01-05 10:23:33

IE9预订火车票

2021-11-07 06:52:44

Windows 11操作系统微软
点赞
收藏

51CTO技术栈公众号