基于docker搭建读写分离、主从复制的Mysql集群

376 阅读7分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。    

一、 mysql主从复制原理

在这里插入图片描述

   在集群中,有3台服务器或者2n+1 台服务器,其中有一台服务器是master服务器,其他为slave服务器,master服务器负责用户写入到数据库里的操作,而其他服务器用来负载用户读取数据, 集群里的服务器通过主服务器复制数据到从服务器的方式来保证数据的一致性,这里不细述同步的原理,下面阐述如何基于docker搭建一个读写分离、主从复制的mysql集群。

二、 搭建集群

  默认你的docker环境已经装好,已经下载好了mysql:5.7的镜像, 如果没有下载mysql镜像,那么可以使用如下命令下载mysql镜像:

docker pull mysql:5.7

在这里插入图片描述

1. 准备需要挂载的配置文件

由于本机的ubuntu装Vim不成功,为了节约时间,就采取了挂载配置的方式。准备三个配置文件,其中server_id可以自己命名,确保三台服务器的server-id不一样即可,分别存放到以下ubuntu或者centos服务器的指定位置:

/home/data/mysql/masterconf
/home/data/mysql/slave1
/home/data/mysql/slave2

配置文件里的内容分别为: master:

!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
[mysqld]
server-id=100

slave1:

!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
[mysqld]
server-id=101
log-bin=mysql-slave1-101-bin

slave2:

!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
[mysqld]
server-id=102
log-bin=mysql-slave2-102-bin

在这里插入图片描述

2. 启动mysql容器

   在服务器上准备好配置文件后,接下来我们就可以启动三个mysql容器,命令如下, 密码可以设置一样,也可以设置不同,看怎么方便怎么来,但在生产环境中,密码应该尽可能地复杂, 这里我把root用户的密码统一设置为:z.#234678.另外端口分别映射到容器的3306,3307,3308。 mysql日志文件以及data文件在Linux环境下所在的默认路径:
/var/lib/mysql mysql配置所在的默认路径: /etc/mysql/mysql.cnf 在这里插入图片描述

master:

docker run -itd --name my-mysql -d \
-p 3306:3306 \
-v /home/data/mysql/masterconf/mysql.cnf:/etc/mysql/mysql.cnf \
-e MYSQL_ROOT_PASSWORD=z.#234678. mysql:5.7

slave1:

docker run -itd --name mysql-slave1 -d \
-p 3307:3306 \
-v /home/data/mysql/slave1/mysql.cnf:/etc/mysql/mysql.cnf \
-e MYSQL_ROOT_PASSWORD=z.#234678. mysql:5.7

slave2:

docker run -itd --name mysql-slave2 -d \
-p 3308:3306 \
-v /home/data/mysql/slave2/mysql.cnf:/etc/mysql/mysql.cnf \
-e MYSQL_ROOT_PASSWORD=z.#234678. mysql:5.7

使用docker ps命令查看容器是否启动成功: 在这里插入图片描述 首先确保3个服务器都能够被访问到,可以直接使用navicat连接测试一下, ip地址一样,端口不同,如果能连接成功,那么就会显示出绿色的状态,如果不能成功,确认ip地址和密码是否正确。 在这里插入图片描述

3. slave服务器配置master

   三台服务器启动成功后,我们需要想办法把其中的两台用来从服务器,一台当做master服务器。下面我选择My-mysql来当做maser服务器:

1 ) 查看主库的status,获取到最新的position

注: 对mysql容器操作,需要先通过指令进入到mysql容器里,指令如下:

docker exec -it my-mysql bash

   position相当于数据库读写的指针,对应的数值表示当前指针的位置。 在这里插入图片描述

2) 查看主库的ip地址

   我们要更改当前服务器的身份为slave,只需要重新设置当前服务器的master即可,绑定的方式通过ip地址来绑定,集群中的mysql在同一个网段下,因此可以实现互通。    docker查看容器的ip地址命令, 参数为容器的id或者名称:

docker inspect --format='{{.NetworkSettings.IPAddress}}'  CONTINAERID/NAMES

在这里插入图片描述

3) 从库slave获取复制的权限

   slave要想从master那儿同步数据,那么先需要给slave创建指定的用户,进行授权REPLICATION SLAVE 权限,这里设置的用户为: replication-mysql ,密码为: z.#234678. , 密码可以与前面的数据库访问的密码不同。

  CREATE USER 'replication-mysql'@'%' IDENTIFIED BY 'z.#234678.';
  GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'replication-mysql'@'%';
  flush privileges;

4) 从库slave绑定主库master的ip

   从库slave获取到权限后,就可以通过以下命令来设置自己的master:

change master to master_host='172.17.0.4', master_user='replication-mysql', master_password='z.#234678.', master_port=3306, master_log_file='mysql-bin.000005', master_log_pos=21681, master_connect_retry=60;

注: 参数master_log_file和master_log_pos 为master库中查询出来的,通过show master status指令查看。

5) 在从服务器中开启slave

   绑定ip完后,可以通过show slave status\G; 来查看slave是否开启,默认是未开启的状态,我们可以通过以下命令开启slave:

mysql> start slave;

开启成功后,执行show slave status\G;如果slave_io_running和slave_sql_running都显示出yes,那么表示slave已经可以正常复制!

在这里插入图片描述

另外记录一下我在从服务器使用指令启动时报错的问题: mysql>start slave; 在这里插入图片描述 解决办法: 1. 检查是否给从服务器设置授权用户 2. 检查chagemaster里的用户配置的密码是否正确,如果不正确也会出现开启失败的问题! 如果需要删除从服务器的slave配置,可以在Mysql里使用如下命令:

stop slave;
reset slave all;

4. 验证同步过程

接下来,在master数据库里进行操作,数据库以及表的信息将都会同步到Slave服务器, 可以发现从数据库会从主数据库里进行同样的操作。

在这里插入图片描述

三. 存在的问题

   上述方法,虽然搭建成功了,但是并没有将数据库的data外挂到磁盘上,就是mysql存的数据依然在镜像的容器里,如果容器删除了,那么数据也会消失,因此以下步骤将实现将数据docker里的mysql容器里的数据挂载(持久化)到磁盘上。

1. 挂载配置。

   在磁盘上新建目录里,/home/data/mysql/{master,slave1,slave2},, 分别新建一个conf目录, 在这里插入图片描述    将mysql容器里的所有相关配置,默认在/etc/mysql/ 目录下, 拷贝到 /home/data/mysql/{master,slave1,slave2}/conf 目录下:

master:
docker cp mysql-master:/etc/mysql /home/data/mysql/master/conf

slave1:
docker cp mysql-master:/etc/mysql /home/data/mysql/slave1/conf

slave2:
docker cp mysql-master:/etc/mysql /home/data/mysql/slave2/conf

   修改配置,配置binlog,主从复制的时候会用到,因为binlog会生成在mysql的数据目录存放的地方,因此binlog需要配置到/var/lib/mysql/ 目录下, 在外挂时,会将该目录复制一份到我们指定的外挂目录下,这样数据和binlog都被提取到了mysql容器外,以达到数据持久化的目的。 log-bin=/var/lib/mysql/mysql-bin

# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2.0,
# as published by the Free Software Foundation.
#
# This program is also distributed with certain software (including
# but not limited to OpenSSL) that is licensed under separate terms,
# as designated in a particular file or component or in included license
# documentation.  The authors of MySQL hereby grant you an additional
# permission to link the program and your derivative works with the
# separately licensed software that they have included with MySQL.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License, version 2.0, for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA

#
# The MySQL  Server configuration file.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html

[mysqld]
pid-file	= /var/run/mysqld/mysqld.pid
socket		= /var/run/mysqld/mysqld.sock
datadir		= /var/lib/mysql
#log-error	= /var/log/mysql/error.log
# By default we only accept connections from localhost
#bind-address	= 127.0.0.1
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
log-bin=/var/lib/mysql/mysql-bin
server-id=100

最终实现的效果如下: 在这里插入图片描述

2. 挂载数据data。

  mysql的data数据默认存放在 /var/lib/mysql 目录下, 因此我们可以使用以下命令在启动的时候挂载data: master:

docker run -itd --name mysql-master -d \
-p 3306:3306 \
-v /home/data/mysql/master/data_and_log:/var/lib/mysql  \
-v /home/data/mysql/master/conf/mysql:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=password mysql:5.7

slave1:

docker run -itd --name mysql-slave1 -d \
-p 3307:3306 \
-v /home/data/mysql/slave1/data_and_log:/var/lib/mysql  \
-v /home/data/mysql/slave1/conf/mysql:/etc/mysql  \
-e MYSQL_ROOT_PASSWORD=password mysql:5.7

slave2:

docker run -itd --name mysql-slave2 -d \
-p 3308:3306 \
-v /home/data/mysql/slave2/data_and_log:/var/lib/mysql   \
-v /home/data/mysql/slave2/conf/mysql:/etc/mysql  \
-e MYSQL_ROOT_PASSWORD=password mysql:5.7

3. 开启不了binlog的问题

   检查mysql.conf.d目录下的mysqld.cnf文件是否配置log-bin。

参考博客: www.cnblogs.com/cpw6/p/1159…