MySQL-基于docker实现Replication集群主从复制及读写分离
阅读原文时间:2021年04月25日阅读:1

什么是MySQL集群

MySQL集群是一个无共享的(shared-nothing)、分布式节点架构的存储方案,其目的是提供容错性和高可用性能。
说的直白一点就是要做一件事,一个人做着非常吃力,没有那么多精力,所以需要多个人分工合作,最终一起完成。MySQL集群就是这个道理,比如读写分离等等。这个说的比较简单了,今天这篇文章就是一个简单的一主一从双节点的Replication集群,为了测试使用。介绍两种数据同步方案来实现主从和读写分离。

关于MySQL集群方案介绍(Replication,PXC)

MySQL的常用集群有很多种:mysql cluster,nbd,MHA,Mariadb Galera cluster,Replication,Percona XtraDB Cluster。
本来我是想一起写这个Replication(本文以下简称Rep)Percona XtraDB Cluster(PXC)两种方案的实现的,不过篇幅太长。这一篇先来写Rep的实现。
先来大概说下这两种方案的优劣势:

  • Replication 采用异步复制,无法保证数据的准确性。我们写入数据操作的只是master节点,只要操作master成功了就算是成功了。至于master节点是否将数据传输给slave几点,客户端是不知道的。写入速度快,但是无法保证数据的强一致性。
  • PXC 同步复制,事务在所有的集群节点要不就同时提交,要不就不提交。它是对一个节点的操作有了准确的成功返回标识后,才会对其他节点同步操作,是以牺牲性能为代价保证强一致性的。

从上面两条信息来看,很多人会觉得明显是PXC集群方案更好啊,不过真的是这样吗?显然,一个事物存在就有其存在的道理。来看下下面的介绍:
不同于pxc集群方案的是,Rep集群方案无法保证数据的强一致性,自然性能稍微好一点,保证一致性的代价就是牺牲性能,保存一些非高价值的数据,例如订单之外的数据等。

比如大数据领域的协同过滤算法分析行为的算法,数据源就是日志,比如商品浏览日志,单条价值不大,积累起来价值达,但是你说这些数据敏感吗?显然不是非常重要比起订单数据。所以在考虑性能后这里就可以采用Rep方案实现,至于订单等一些敏感数据必须采用可保证强一致性的集群方案,比如PXC。

简单点说,最终结果就是你可以搭建多个集群,重要的数据存储在PXC集群中,不是那么重要的数据存储在Rep集群中。保证性能的同时,保证数据的完整一致性。

注意: PXC集群并不是说节点越多读写速度就越快,恰恰相反,节点越多,同步的消耗就越大,所以,小规模的重要数据节点集群使用PXC很不错。集群性能的好坏取决于整个集群中性能最差的主机的配置性能,还是木桶装水问题。

来看几个案例:
16年微信红包支付峰值15.8W次/秒刷新世界纪录。

17年天猫双11数据库读写峰值4200W次/秒,可支付峰值为25.6W次/秒,再次刷新世界纪录,为什么差距这么大,这就是因为支付数据是很重要敏感的数据,必须保证强一致性,所以整个的读写成本高,峰值自然较低。
由上面的例子就可以看出,整个的大型高可用数据库集群并不是单纯的节点都建立在pxc集群中,重要等级不高的数据可以在Replication集群中操作,降低整体数据库架构的压力。

所以没有技术存在了就没有好与坏,取决于你需不需要。
好了,不说太多文字性描述了,直接开始试验。

环境

该文的所有测试都是基于docker部署的,如果没有使用过或者不是很了解的自己查阅一下先关资料,保证基础的使用就可以完成以下配置搭建。如果你实在不想去使用docker,那你用虚拟机也可以,配置大同小异,几乎没有差距。

1.使用日志文件实现主从

1.1准备工作

首先我们拉取一个MySQL5.7的镜像,一会就使用这个镜像来创建运行几个MySQL容器来做实验。

docker pull mysql:5.7

完成后如下:

然后你需要创建几个文件夹,用来挂载容器中的文件。你可以按照我这样操作,或者选择别的地方来创建,首先我的位置(如果你选择别的位置,命令中的文件夹位置请勿写错):

/home/guwenjie/docker


创建两个文件夹:mysql-master,mysql-slave-1。表示一个是主节点容器文件挂载位置,一个是从节点。
然后分别在两个文件夹中创建三个文件夹confdatalogs。那个timezone不用管,哪个是时区文件,一会执行相应命令即可。如下:

1.2创建mysql-master主节点MySQL容器并运行

现在需要创建运行MySql容器了。首先,设置时区:

echo "Asia/shanghai" > /home/guwenjie/docker/mysql-master/timezone

然后执行docker run命令来创建master主节点容器并运行:

docker run -p 3307:3306 --name mysql-master 
-v /home/guwenjie/docker/mysql-master/conf:/etc/mysql/conf.d 
-v /home/guwenjie/docker/mysql-master/logs:/logs 
-v /home/guwenjie/docker/mysql-master/data:/var/lib/mysql 
-v /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime 
-v /home/guwenjie/docker/mysql-master/timezone:/etc/timezone 
-e MYSQL_ROOT_PASSWORD=123456 -d docker.io/mysql:5.7

大概解释一下这条命令,启动了一个Mysql容器,名字叫做mysql-master,容器的3306端口映射到了宿主机的3307端口(为什么是3307,这个你随便定,因为我的服务器上的3306端口已经被LNMP环境占用),然后容器中的conf.d挂载到了/home/guwenjie/docker/mysql-master/conf,其他几个挂载同理。
最后的是账户信息,账户:root,密码:123456。

1.3创建mysql-slave-1从节点MySQL容器并运行

echo "Asia/shanghai" > /home/guwenjie/docker/mysql-slave-1/timezone

然后执行docker run命令来创建master主节点容器并运行:

docker run -p 3308:3306 --name mysql-slave-1 
-v /home/guwenjie/docker/mysql-slave-1/conf:/etc/mysql/conf.d 
-v /home/guwenjie/docker/mysql-slave-1/logs:/logs 
-v /home/guwenjie/docker/mysql-slave-1/data:/var/lib/mysql 
-v /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime 
-v /home/guwenjie/docker/mysql-slave-1/timezone:/etc/timezone 
-e MYSQL_ROOT_PASSWORD=123456 -d docker.io/mysql:5.7

不做过多解释了。docker简单了解下这些东西都可以正常使用,并且真心推荐学习使用,非常方便。

1.4查看运行的两个节点容器

docker ps -a


你可以看到这两个运行中的容器和相关信息。

1.5创建主从节点的配置文件

这个是重点,关系到主从的实现。配置一定不能出错,其实配置非常简单。
主节点:/home/guwenjie/docker/mysql-master/conf,创建master.cnf文件
配置:

[mysqld]
server-id=1
log-bin=mysql-bin

从节点:/home/guwenjie/docker/mysql-slave-1/conf,创建slave.cnf文件
配置:

[mysqld]
server_id=2
log-bin=mysql-bin
binlog-format=ROW
#忽略同步的表 
binlog_ignore_db=mysql
binlog_ignore_db=information_schema
binlog_ignore_db=performation_schema
binlog_ignore_db=sys

另外,我们先看下这两个节点的容器真实ip,记下来,后面会用到。
命令:docker inspect 容器名称或者ID | grep IPAddress

docker inspect  mysql-master | grep IPAddress


所以,mysql-master主节点容器的真实IP就是(你的自行查询):172.17.0.2

1.6MySQL容器内部相关配置

1.6.1主库配置

先进入主库节点创建一个用户,待会从库使用该用户来实现基于log文件的主从复制。
进入主节点容器:

docker exec  -it mysql-master /bin/bash

登录MySQL,当初记得我们创建的是root/123456

mysql -uroot -p

创建新用户并授权(user你自己定义,只要从库配置的时候别写错就行)

CREATE USER 'guwenjie-m'@'%' IDENTIFIED BY '123456';

授权

GRANT REPLICATION SLAVE ON *.* TO 'guwenjie-m'@'%';

刷新,切记要刷新

FLUSH PRIVILEGES;

查看主库状态

show master status;


记清楚这里的bin-log文件是:mysql-bin.000007,你的可能不同,同上,从库配置对应正确的就行。

1.6.2从库配置

进入从库节点容器:

docker exec  -it mysql-slave-1 /bin/bash

登录MySQL,1.3步骤中我们创建的从库命令中,数据库也是:root/123456

mysql -uroot -p

首先停止slave节点

stop slave;

配置
说明:

  • MASTER_HOST=172.17.0.2,是我们在1.5末尾查询出的主库容器

  • MASTER_USER='guwenjie-m',使我们在1.6.1中创建并授权的账户

  • MASTER_PORT=3306这里要注意啊,不要填写成映射到宿主机中的端口,因为实际主从还是数据库真实IP+端口来实现的,所以默认3306

  • MASTER_LOG_FILE='mysql-bin.000007',这个就是1.6.1末尾show master status;看到的file名称

    CHANGE MASTER TO
    MASTER_HOST='172.17.0.2',
    MASTER_USER='guwenjie-m',
    MASTER_PORT=3306,
    MASTER_PASSWORD='123456',
    MASTER_LOG_FILE='mysql-bin.000007',
    MASTER_LOG_POS=1415;

然后重置slave

reset slave;

启动slave

start slave;

可以查看一下slave启动后的情况,查看一下基本信息以及最重要的从库的IO和SQL是否正常
从库信息较多,加上\G参数查看方便。

show slave status \G;


到此为止,配置完成。虽然写的比较多,实际没有多少操作。下面就是测试
这时候你应该还在容器内部,两次exit退出容器。第一次退出sql,第二次退出容器。

1.7测试

重启主库和从库容器

docker restart mysql-master


docker restart mysql-slave-1

测试,我用Navicat管理工具给大家演示一下,首先连接两个主库和从库。
注意:

  • 连接IP是宿主机IP,而不是容器的真是IP
  • 端口是映射到宿主机的端口。如3307,3308…
  • 账号密码就是我们执行docker run 命令中的设置的root账户和123456密码

    插入数据,我做了一个gif图,可以看下:

    写的篇幅有点长了,本来还有第二种方式,基于GTID实现主从的,这篇先到这里,后续补充上或者另写一篇基于GTID实现主从的文章。
    本篇的实验只有两个节点,你可以多加几台从库配置测试。
    提一下GTID,这个是在MySQL5.7.6之后新加入的机制,基于事务的主从方案。就是为了弥补第一种方式的弊端。第一种会出现,master写入成功,但是slave复制失败,这时候,会出现,主库写入,从库读取不到情况。GTID模式是基于事务的,每一个事务有一个唯一的GTID标识,master的写入必须是slave都复制成功后才会真正commit,不然会回滚。解决了一致性问题。作用类似与上面的PXC。但是敏感数据还是建议直接采用PXC这类可保证数据强一致性的方案。

先到这里,有什么问题可随时留言~~~