# 高可用 Replication 集群

上一章,创建了第一组的 3 个容器

REP 1

虚拟机 IP 地址 端口 容器 数据卷
docker-1 192.168.56.105 9003 rn1(m) rnv1
docker-2 192.168.56.107 9003 rn2(s) rnv2
docker-3 192.168.56.108 9003 rn3(m) rnv3
docker-1 192.168.56.105 9004 rn4(s) rnv4

REP 2

虚拟机 IP 地址 端口 容器 数据卷
docker-2 192.168.56.107 9004 rn5(m) rnv5
docker-3 192.168.56.108 9004 rn6(s) rnv6

由于这里,笔者没有开 4 台虚拟机,所以只完成了第一个集群的双主搭建,第二个集群还是单主

# 前面创建了 rn1 容器,这里创建 rn2 容器
# 同时把 rn3 和 rn4 也创建好
[root@study ~]# docker run -d -p 9003:3306 --name rn2 -e MYSQL_ROOT_PASSWORD=123456 -v rnv2:/var/lib/mysql --privileged --net=swarm_mysql mysql
1
2
3

# 创建同步账户

从节点需要先登录到主节点,然后才可以复制 binlog 日志,所以要在 主节点 上创建一个用于数据同步的账户

注意

因为 root 用户权限太高,默认也是不允许远程登录,我们创建普通用户来同步数据。

另外,注意:在开启 binlog 日志之前创建同步用户。否则只能删掉容器从来了。

为了方便,使用 UI 来创建用户

image-20200627121618088

在服务器权限里面勾选 3 个权限:Super、Reload、Replication Slave

# 配置主节点

修改配置文件 /etc/mysql/my.cnf ,加上如下参数

[mysqld]
character_set_server = utf8
server_id = 1001
log_bin = mysql_bin
relay_log = relay_bin
log-slave-updates = 1
sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
1
2
3
4
5
6
7
  • server_id:在 Replication 集群节点中的名称,一个唯一标识

  • log_bin:开启 binlog 日志,日志名字为 mysql_bin

  • relay_log:开启 relay_log 日志,并对日志命名

    由于配置的是双主,即是主、也是从。所以要开启

  • log-slave-updates

    由于是要配置双主,在 rn3 节点中,rn1 是从节点,所以从节点要把查询语句也记录在 binlog 日志中,rn3 才能同步到写入的数据。

  • sql_model:这里主要设置的是数据同步的模式

    NO_ENGINE_SUBSTITUTION:创建表的时候,不指定引擎,用默认的 InnoDB

    STRICT_TRANS_TABLES:使用事物,在执行 事物 SQL 的时候,执行失败就回滚

配置文件不是存放在数据卷中的,所以需要在容器中修改,容器安装 vim 如果慢的话,可以尝试使用数据卷来做中转目录:

  • 拷贝配置文件在数据卷中,在宿主机上修改

    [root@study ~]# docker exec -it rn1 bash
    root@31c9dda3c63c:~# cp /etc/mysql/my.cnf /var/lib/mysql
    
    1
    2
  • 再把数据卷中的配置文件覆盖原位置的配置文件

    root@31c9dda3c63c:~# cp /var/lib/mysql/my.cnf /etc/mysql
    
    1

修改完成之后,重启 rn1 容器,然后去数据卷中查看是否有 binlog 的日志文件产生。如果没产生,貌似只能删掉容器重新来一次了,起不起来,就进入不了容器,也修改不了配置文件(肯定是配置文件写错了导致的)

cd /var/lib/docker/volumes/rnv1/_data
# 能看到如下文件,就表示可 binlog 开启了已经
-rw-r----- 1 polkitd input      154 622 01:19 mysql_bin.000001
-rw-r----- 1 polkitd input       19 622 01:19 mysql_bin.index
1
2
3
4

在 index 中保存了创建的所有 binlog 日志文件名称。

那个 relay_log 要连接上主节点,自己作为从节点复制的时候才会出现 relay_log 的文件

再把 rn3 也按照这个配置一下,server_id 记得不要重复了。

# 配置从节点

修改配置文件 /etc/mysql/my.cnf ,加上如下参数

[mysqld]
character_set_server = utf8
server_id = 1002
log_bin = mysql_bin
relay_log = relay_bin
read-only = 1

1
2
3
4
5
6
7
  • read-only:从设置为只读。普通账户只能读

配置完成后,重启对应的容器,这里配置了 rn2 和 rn4

# 设置主从同步

从节点上 执行如下的语句

# 停止同步服务
stop slave;

# 改变 master
# 在 Swarm 中 ip 不是固定的,建议写主机名,也就是容器名
# 包括端口也是容器的端口
# 因为这个是容器和容器间的交互
change master to master_host='rn1',master_port=3306,master_user='backup',master_password='123456';

# 开启同步服务
start slave;
1
2
3
4
5
6
7
8
9
10
11

注意 master_host ,rn2 连接的是 rn1,rn4 连接的是 rn3,我们之前的规划别搞混了。

# 检查主从同步状态

在从节点上执行 show slave status ,查看结果

Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_UUID Master_Info_File SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State Master_Retry_Count Master_Bind Last_IO_Error_Timestamp Last_SQL_Error_Timestamp Master_SSL_Crl Master_SSL_Crlpath Retrieved_Gtid_Set Executed_Gtid_Set Auto_Position Replicate_Rewrite_DB Channel_Name Master_TLS_Version
Waiting for master to send event rn1 backup 3306 60 mysql_bin.000001 154 relay_bin.000002 367 mysql_bin.000001 Yes Yes 0 0 154 568 None 0 No 0 No 0 0 1001 23855481-b3d8-11ea-987d-02420a000003 /var/lib/mysql/master.info 0 NULL Slave has read all relay log; waiting for more updates 86400 0

内容有很多,我们关注两个属性:Slave_IO_RunningSlave_SQL_Running,如果都为 yes 就表示 主从同步成功了。

这里要配置:rn2 挂到 rn1 下,rn4 挂到 rn3 下

# 主节点双向同步

配置同步方式,上面有,这里配置两次

  • rn1 配置为 rn 3 的从节点
  • rn3 配置为 rn1 的从节点

注意:在 Navicat 上操作的时候,不要操作错数据库了

配置完成之后,就可以测试下是否生效:在 rn1 和 rn3 上写入数据,查看 4 个节点中的数据是否有同步(因为我们配置的是双主同步,一个写节点写入数据,4 个节点上都会有该数据)

# 配置第二个集群

REP 2

虚拟机 IP 地址 端口 容器 数据卷
docker-2 192.168.56.107 9004 rn5(m) rnv5
docker-3 192.168.56.108 9004 rn6(s) rnv6

前面说过了,笔者机器不够,第二个就创建一个单主的集群

# mycat 配置双主节点

之前是 1 个写节点 2 个读节点;现在是双主:1 个写,一个读

schema.xml

  <!-- rep1 集群-->
  <dataHost name="rep1" maxCon="1000" minCon="10" balance="3"
            writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
    <heartbeat>select user()</heartbeat>
     <!-- 第一个写 -->
    <writeHost host="r1w1" url="192.168.56.105:9003" user="root" password="123456">
      <readHost host="r1r1" url="192.168.56.107:9003" user="root" password="123456"/>
    </writeHost>
     <!-- 第二个写 -->
     <writeHost host="r1w2" url="192.168.56.108:9003" user="root" password="123456">
      <readHost host="r1r2" url="192.168.56.105:9004" user="root" password="123456"/>
    </writeHost>
  </dataHost>
  <!-- rep2 集群-->
  <dataHost name="rep2" maxCon="1000" minCon="10" balance="3"
            writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
    <heartbeat>select user()</heartbeat>
    <writeHost host="r2w1" url="192.168.56.107:9004" user="root" password="123456">
      <readHost host="r2r1" url="192.168.56.108:9004" user="root" password="123456"/>
    </writeHost>
  </dataHost>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21