云原生|kubernetes|部署MySQL一主多从复制集群(基于Binlog+Position的复制)
让主库负责写,从库负责读,这样,即使主库出现了锁表的情景,通过读从库也可以保证业务的正常运作。MySQL单实例的部署。附1:GTID的概念。主从复制报错排查示例。
前言:
MySQL集群的架构比较多,目前来说,基本没有一个统一的标准,常见的集群架构是MySQL cluster(官方的)或者简单的一主多从式集群。下面说一下主从复制的一下概念。
MySQL 主从复制概念
MySQL 主从复制是指数据可以从一个MySQL数据库服务器主节点复制到一个或多个从节点。MySQL 默认采用异步复制方式,这样从节点不用一直访问主服务器来更新自己的数据,数据的更新可以在远程连接上进行,从节点可以复制主数据库中的所有数据库或者特定的数据库,或者特定的表。
MySQL 主从复制主要用途
-
读写分离
在开发工作中,有时候会遇见某个sql 语句需要锁表,导致暂时不能使用读的服务,这样就会影响现有业务,使用主从复制,让主库负责写,从库负责读,这样,即使主库出现了锁表的情景,通过读从库也可以保证业务的正常运作。
-
数据实时备份,当系统中某个节点出现故障的时候,方便切换
-
高可用HA
-
架构扩展
随着系统中业务访问量的增大,如果是单机部署数据库,就会导致I/O访问频率过高。有了主从复制,增加多个数据存储节点,将负载分布在多个从节点上,降低单机磁盘I/O访问的频率,提高单个机器的I/O性能。
MySQL主从形式
一主一从

一主多从,提高系统的读性能

一主一从和一主多从是最常见的主从架构,实施起来简单并且有效,不仅可以实现HA,而且还能读写分离,进而提升集群的并发能力。下面的示例将基于此架构做演示。
多主一从 (从5.7开始支持)

多主一从可以将多个mysql数据库备份到一台存储性能比较好的服务器上,一般这种架构是不使用的。
双主复制

双主复制,也就是互做主从复制,每个master既是master,又是另外一台服务器的slave。这样任何一方所做的变更,都会通过复制应用到另外一方的数据库中。
级联复制

级联复制模式下,部分slave的数据同步不连接主节点,而是连接从节点。因为如果主节点有太多的从节点,就会损耗一部分性能用于replication,那么我们可以让3~5个从节点连接主节点,其它从节点作为二级或者三级与从节点连接,这样不仅可以缓解主节点的压力,并且对数据一致性没有负面影响。
MySQL 主从复制原理
MySQL主从复制涉及到三个线程,一个运行在主节点(log dump thread),其余两个(I/O thread, SQL thread)运行在从节点,如下图所示:

- 主节点 binary log dump 线程作用
当从节点连接主节点时,主节点会创建一个log dump 线程,用于发送bin-log的内容。在读取bin-log中的操作时,此线程会对主节点上的bin-log加锁,当读取完成,甚至在发动给从节点之前,锁会被释放。
- 从节点I/O线程作用
当从节点上执行start slave命令之后,从节点会创建一个I/O线程用来连接主节点,请求主库中更新的bin-log。I/O线程接收到主节点binlog dump 进程发来的更新之后,保存在本地relay-log中。
反应在SQL语句,slave status \G 这里,该线程就是 slave_io_running。
- 从节点SQL线程作用
SQL线程负责读取relay log中的内容,解析成具体的操作并执行,最终保证主从数据的一致性。
反应在SQL语句,slave status \G 这里,该线程就是 slave_sql_running。
对于每一个主从连接,都需要三个进程来完成。当主节点有多个从节点时,主节点会为每一个当前连接的从节点建一个binary log dump 进程,而每个从节点都有自己的I/O进程,SQL进程。从节点用两个线程将从主库拉取更新和执行分成独立的任务,这样在执行同步数据任务的时候,不会降低读操作的性能。比如,如果从节点没有运行,此时I/O进程可以很快从主节点获取更新,尽管SQL进程还没有执行。如果在SQL进程执行之前从节点服务停止,至少I/O进程已经从主节点拉取到了最新的变更并且保存在本地relay日志中,当服务再次起来之后,就可以完成数据的同步。
一,
实验目标:
在kubernetes集群内搭建一个单主多从复制的MySQL集群 ,并通过
MySQL镜像采用最接近MySQL8的mysql-5.7.39版本,使用此版本的原因是该版本支持GTID,也就是说扩展性更好。
部署完成后的测试工作主要是使用Navicat permium 15来进行,此版本对于比较新的MySQL支持较好,如何安装Navicat 就不在此废话了,百度即可。
附1:GTID的概念:
从Mysql5.6.5版本开始增加的一种主从复制方法:GTID,其全称是Global Transaction Identifier,即全局事务标识。通过GTID保证每个主库提交的事务在集群中都有唯一的一个事务id。强化了数据库主从的一致性和故障恢复数据的容错能力。在主库宕机发生主从切换的情况下,GTID方式可以让其他从库主动找到新主库复制的位置,而且GTID可以忽略已经执行过的事务,减少了数据发生错误的概率。
组成:GTID是对一个已经提交事务的编号,并且是全局唯一的。GTID是由UUID和TID组成的。UUID是Mysql实例的唯一表示,TID代表该实例已经提交的事务数量,随着事务提交数量递增。
二,
MySQL单实例的部署
云原生|kubernetes|静态pod和静态pod的应用_晚风_END的博客-CSDN博客 具体部署方法见此文,考虑内容比较多,就不在此文内重复了。
三个节点的IP是:192.168.217.16,192.168.217.17,192.168.217.23。192.168.217.16作为master。Navicat新建的连接统一以IP后缀为名,例子如下:

关于MySQL的配置文件:
如果是按照上面给的教程部署,那么,MySQL的配置文件应该是在 /opt/mysql/conf 目录下的mysqld.cnf 文件,这个配置文件写的很全,基本所有能配置的地方都配置了,只是需要更改一下server_id,例如,master节点192.168.217.16,可以设置 server_id 为56116,slave节点192.168.217.17,可以设置server_id 为56117,23服务器设置server_id 为56123。总之,server_id 必须是不同的。
三,
一主多从MySQL集群的配置
192.168.217.16 master节点的配置
1 ,
在master节点也就是192.168.217.16服务器上,执行以下SQL命令:
select user,host,authentication_string,plugin from user;
此命令输出结果如下:

可以看到只有root用户并且开启了root用户的远程连接权限,下面需要添加一个slave用户,此用户专门做同步日志的工作。
2,
slave 同步日志专用用户的建立
CREATE USER 'slave'@'192.168.217.17' IDENTIFIED WITH mysql_native_password BY '123456';
CREATE USER 'slave'@'192.168.217.23' IDENTIFIED WITH mysql_native_password BY '123456';
此命令为新建用户slave,该用户只可以远程连接从节点17,密码为123456
此命令为新建用户slave,该用户只可以远程连接从节点17,密码为123456,此时用户状态应该是这样的:

3,
slave同步日志专用用户的权限分配
GRANT REPLICATION SLAVE ON *.* TO 'slave'@'192.168.217.17';
GRANT REPLICATION slave ON *.* TO 'slave'@'192.168.217.23';
此命令为给用户slave赋予远程复制master数据库的所有库表的权限
4,
查询同步端点和需要同步的日志文件名称
show master status; 输出如下,由于MySQL的配置文件内是同时开启了GTID,因此,最后是有显示GTID的,不过该值目前不需要使用,主要是mysql_binlog.000011和端点2250
192.168.217.17从节点的配置
执行以下SQL语句
这个change命令主要是设置master的ip和端口,使用的用户名称,用户密码,要同步的日志文件名称和日志端点,要和show master status的输出一致。
此命令可以反复执行,如果定义有误只是不能数据同步而已,对数据库的运行并无影响。
stop slave;
CHANGE MASTER TO MASTER_HOST='192.168.217.16',
MASTER_PORT=3311,
MASTER_USER='slave',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='mysql_binlog.000011',
MASTER_LOG_POS=2250;
此时可以启动slave同步,并查看同步状态了,由于下面的查看命令在Navicat里会显得很长一段不利于观察,并且报错日志不会显示,因此,是在MySQL的cmd里运行:
start slave;
show slave status \G
输出的日志如下:
[root@node3 manifests]# mysql -uroot -P 3311 -p -h 192.168.217.17
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 5257
Server version: 5.7.39-log MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]>
MySQL [(none)]> show slave status \G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event #此状态表示准备同步,暂未发现master节点给的同步消息,这个是正常的状态
Master_Host: 192.168.217.16
Master_User: slave
Master_Port: 3311
Connect_Retry: 60
Master_Log_File: mysql_binlog.000011
Read_Master_Log_Pos: 2250
Relay_Log_File: k8s-node1-relay-bin.000002
Relay_Log_Pos: 323
Relay_Master_Log_File: mysql_binlog.000011
Slave_IO_Running: Yes #关键进程,必须为yes,表示同步功能正常
Slave_SQL_Running: Yes #关键进程,必须为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: 2250
Relay_Log_Space: 534
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: 56116
Master_UUID: ca9907c5-5dd3-11ed-9029-000c29320c0d
Master_Info_File: /var/lib/mysql/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: 744c48a9-5f72-11ed-a43f-000c29e99e89:1,
ca9907c5-5dd3-11ed-9029-000c29320c0d:9-10:14-16
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
192.168.217.23 从节点的配置:
执行以下SQL语句
这个change命令主要是设置master的ip和端口,使用的用户名称,用户密码,要同步的日志文件名称和日志端点,要和show master status的输出一致。
此命令可以反复执行,如果定义有误只是不能数据同步而已,对数据库的运行并无影响。
stop slave;
CHANGE MASTER TO MASTER_HOST='192.168.217.16',MASTER_PORT=3311,MASTER_USER='slave',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql_binlog.000011',MASTER_LOG_POS=2250;
查看从节点状态:
start slave;
show slave status;
同理,cmd登录192.168.217.23数据库,输出如下:
[root@node3 manifests]# mysql -uroot -P 3311 -p -h 192.168.217.23
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 4782
Server version: 5.7.39-log MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]> show slave status \G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.217.16
Master_User: slave
Master_Port: 3311
Connect_Retry: 60
Master_Log_File: mysql_binlog.000011
Read_Master_Log_Pos: 2250
Relay_Log_File: node3-relay-bin.000002
Relay_Log_Pos: 323
Relay_Master_Log_File: mysql_binlog.000011
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: 2250
Relay_Log_Space: 530
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: 56116
Master_UUID: ca9907c5-5dd3-11ed-9029-000c29320c0d
Master_Info_File: /var/lib/mysql/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: ae4751af-5d31-11ed-8ed7-000c29701212:1
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
至此,MySQL的单主多从复制就搭建完毕了,下面进入测试环节。
四,
测试主从复制功能:
在master节点192.168.217.16数据库上建立一个库,库名mytest:
create database mytest;
show databases;
输出如下;

在slave服务器192.168.217.17上查看数据库,可以看到多出一个mytest数据库,同理,在23服务器上也可以看到测试数据库mytest。
现在回到master节点,删除这个测试数据库:
drop database mytest;
show databases;
在master上可以确认确实删除了测试数据库:

在从节点192.168.217.17上,可以看到测试数据库也没有了,同理,在23服务器上也是可以看到同样的结果,说明主从复制功能完好。
需要注意的是,主节点是读写均可(也就是增删改查,函数等等),从节点只能读操作(也就是查询操作),如果你非要在从节点建库建表,做增删改查,那么,是不会在其它节点同步并且看到的。
附2,
主从复制报错排查示例:
1,在主从复制原理里,提到过slave_io_running和slave_sql_running, 这两个值如果都为no,如下图所示
MySQL [(none)]> show slave status \G
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: 192.168.217.16
Master_User: slave
Master_Port: 3311
Connect_Retry: 60
Master_Log_File: mysql_binlog.000011
Read_Master_Log_Pos: 2862
Relay_Log_File: node3-relay-bin.000002
Relay_Log_Pos: 935
Relay_Master_Log_File: mysql_binlog.000011
Slave_IO_Running: No
Slave_SQL_Running: No
那么,可能的原因为没有执行start slave 这个命令,在从节点执行完此命令后一般会有正常显示。
2,
Slave_IO_Running: No
查看从节点状态输出如下,可以看到io是No的:
MySQL [(none)]> show slave status \G
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: 192.168.217.16
Master_User: slave
Master_Port: 3311
Connect_Retry: 60
Master_Log_File: mysql-binlog.000011
Read_Master_Log_Pos: 2250
Relay_Log_File: node3-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-binlog.000011
Slave_IO_Running: No
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: 2250
Relay_Log_Space: 154
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: 1236
Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file'
上面的报错,可以看到报错日志为最后一行,这里说的是找不到binlog日志文件:
Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file'
主节点的master status是:

从节点的charge语句是:
CHANGE MASTER TO MASTER_HOST='192.168.217.16',MASTER_PORT=3311,MASTER_USER='slave',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-binlog.000011',MASTER_LOG_POS=2250;
可以看到两个file的名字不一样,一个是mysql_binlog.000011,一个是mysql-binlog.000011
解决方案(先停止slave,在重新执行change命令,使用master的文件名,然后在start slave):
stop slave;
CHANGE MASTER TO MASTER_HOST='192.168.217.16',MASTER_PORT=3311,MASTER_USER='slave',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql_binlog.000011',MASTER_LOG_POS=2250;
start slave;
3,
slave_io_running 是connecting状态
查看从节点状态:
MySQL [(none)]> show slave status \G
*************************** 1. row ***************************
Slave_IO_State: Connecting to master
Master_Host: 192.168.217.16
Master_User: slave
Master_Port: 3321
Connect_Retry: 60
Master_Log_File: mysql_binlog.000011
Read_Master_Log_Pos: 2250
Relay_Log_File: node3-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql_binlog.000011
Slave_IO_Running: Connecting
Slave_SQL_Running: Yes
发现从节点change语句是这个,端口没有写对,应该是3311的:
CHANGE MASTER TO MASTER_HOST='192.168.217.16',MASTER_PORT=3321,MASTER_USER='slave',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql_binlog.000011',MASTER_LOG_POS=2250;
解决方案:
先停止slave,在重新change,使用正确的端口,在启动slave,就不演示了,和上面的一样。
小结:
以上错误通常都是change语句里的那些配置没有和 show master status 以及 master的IP,端口,用户,用户密码等没匹配到的原因。
以上就是kubernetes集群部署一主多从MySQL集群的简单演示。
更多推荐

所有评论(0)