云原生|kubernetes|部署MySQL一主多从复制集群(基于GTID的复制)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
日志服务 SLS,月写入数据量 50GB 1个月
云数据库 RDS PostgreSQL,高可用系列 2核4GB
简介: 云原生|kubernetes|部署MySQL一主多从复制集群(基于GTID的复制)

前言:

一,

MySQL的主从复制优点如下:

数据更安全:做了数据冗余,不会因为单台服务器的宕机而丢失数据
性能大大提升:一主多从,不同用户从不同数据库读取,性能提升
扩展性更优:流量增大时,可以方便的增加从服务器,不影响系统使用
负载均衡:一主多从相当于分担了主机任务,做了负载均衡。

那么在实操之前,我们还是需要了解一下主从复制的原理:

二,

主从复制的原理:

MySQL的复制功能用三个线程来实现:
主库:Binlog Dump线程
从库:I/O线程和SQL线程
1.用户提交数据的修改,然后Master主库把所有数据库变更写进Binary Log二进制日志。
主库通过Binlog Dump线程把二进制日志内容推送给Slave从库,从库被动接收数据,不是主动获取,除非是新建连接。
2.在从库上执行START SLAVE语句时,已经使用CHANGE MASTER TO语句配置好复制信息,从库会创建一个I/O线程,该线程连接到主库并请求主库为其发送所需的二进制日志。
从库I/O线程与主库Binlog Dump线程成功建立连接后,从库I/O线程接收主库Binlog Dump线程发送的二进制日志,并将它们写入从库本地的Relay Log中继日志文件。
3.从库SQL线程读取并解析中继日志中的内容,按照读取的顺序进行回放,二进制日志中存放的事务顺序就是主库中事务的提交顺序,并将数据变更写入本地数据库文件中,这样就实现了数据在主从数据库实例之间的同步。

三,

主从复制的两种方式

传统复制,也可以称为基于二进制日志文件和位置的复制,在从库中配置复制时,要求指定从库中获取的二进制日志文件(binlog file)和位置(binlog position),也就是基于Binlog+Position的复制。

GTID的复制,新的事务复制方法,利用GTID可以自动在主库寻找需要复制的二进制日志记录,因此不需要关心日志文件或位置,极大地简化了许多常见的复制任务,也就是基于GTID的复制。

MySQL 5.6之前只支持传统复制,即 基于二进制日志文件和位置的复制,在5.6及之后的版本中,出现了基于GTID的复制,而在复制方面,MySQL的版本是向后兼容的(也就是MySQL5.6后可以传统复制也可以GTID复制,看心情咯)

四,

MySQL主从复制的几个关键参数:

这里说的关键参数基本都是和binlog有关的

(1)

sync_binlog

sync_binlog参数来控制数据库的binlog刷到磁盘上去。

默认,sync_binlog=0,表示MySQL不控制binlog的刷新,由文件系统自己控制它的缓存的刷新。这时候的性能是最好的,但是风险也是最大的。因为一旦系统Crash,在binlog_cache中的所有binlog信息都会被丢失。

如果sync_binlog>0,表示每sync_binlog次事务提交,MySQL调用文件系统的刷新操作将缓存刷下去。最安全的就是sync_binlog=1了,表示每次事务提交,MySQL都会把binlog刷下去,是最安全但是性能损耗最大的设置。

这样的话,在数据库所在的主机操作系统损坏或者突然掉电的情况下,系统才有可能丢失1个事务的数据。

(2)

log-slave-updates

log-slave-updates这个参数用来配置从服务器的更新是否写入二进制日志,这个选项默认是不打开的。如果需要配置互为主从,那么,此参数需要配置。

(3)

binlog_format

此参数是binlog日志的格式,格式分为三种:STATEMENT模式(SBR),ROW模式(RBR),MIXED模式(MBR)

binlog_format = STATEMENT

每一条修改数据的sql语句会记录到binlog中。

优点:

并不需要记录每一行的数据变化,减少了binlog日志量,节约IO,提高性能。

缺点:

在某些情况下会导致master-slave中的数据不一致(如sleep()函数, last_insert_id(),以及user-defined functions(udf)等会出现问题)

binlog_format = ROW

不记录每条sql语句的上下文信息,仅需记录哪条数据被修改了,修改成什么样了。

优点:

不会出现某些特定情况下的存储过程、或function、或trigger的调用和触发无法被正确复制的问题。

缺点:

会产生大量的日志,尤其是alter table的时候会让日志暴涨。

binlog_format = MIXED

以上两种模式的混合使用,一般的复制使用STATEMENT模式保存binlog,对于STATEMENT模式无法复制的操作使用ROW模式保存binlog,MySQL会根据执行的SQL语句选择日志保存方式。

在MySQL 5.7.7之前,默认的二进制日志采用statement格式。

在MySQL 5.7.7及更高的版本中,默认的二进制变更为row格式。

建议使用binlog_format = MIXED ,这样可以做到性能和负载的平衡。

(4)

relay_log_recovery = 1

当slave从库宕机后,假如relay-log损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的relay-log,并且重新从master上获取日志,这样就保证了relay-log的完整性。

默认情况下该功能是关闭的,将relay_log_recovery的值设置为 1时,可在slave从库上开启该功能,建议开启。

(5)

enforce_gtid_consistency = TRUE

当使用此参数的时候,事务、存储过程、存储函数和触发器内不支持CREATE TEMPORARY TABLE和DROP TEMPORARY TABLE语句,

不过可以在这些对象之外执行CREATE TEMPORARY TABLE和DROP TEMPORARY TABLE语句,当需要使用autocommit = 1时自动提交。

(6)

使用GTID时不支持使用系统变量sql_slave_skip_counter来跳过事务,也就是说,当使用了 gtid_mode=ON这个参数的时候,不可以使用SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; 一般报错如下:

1858 - sql_slave_skip_counter can not be set when the server is running with @@GLOBAL.GTID_MODE = ON. Instead, for each transaction that you want to skip, generate an empty transaction with the same GTID as the transaction

一,

开启GTID

主节点:192.168.217.16:3311 从节点1:192.168.217.17:3311 从节点2:192.168.217.23:3311

主节点:

主要是设置三个参数,enforce_gtid_consistency = TRUE或者enforce_gtid_consistency = ON都可以

gtid_mode = ON
enforce_gtid_consistency = TRUE
binlog_format = ROW

从节点

也是设置三个参数,enforce_gtid_consistency = TRUE或者enforce_gtid_consistency = ON都可以

gtid_mode = ON
enforce_gtid_consistency = TRUE
binlog_format = ROW

MySQL 5.7.9 及之后的版本新增了一张InnoDB存储引擎的mysql.gtid_executed表来持久化GTID信息(如果没记错的话),因此,MySQL的版本应该使用MySQL5.7.9以后的哦。

二,

从节点执行以下命令:

这里解释一下change命令,复制操作可以使用专有账号也可以使用root用户,使用专有用户需要在master节点创建用户,命令如下:

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';
GRANT REPLICATION SLAVE ON *.* TO 'slave'@'192.168.217.17';
GRANT REPLICATION slave ON *.* TO 'slave'@'192.168.217.23';

在从节点执行change命令:

stop slave;
CHANGE MASTER TO MASTER_HOST='192.168.217.16',MASTER_PORT=3311,MASTER_USER='slave',MASTER_PASSWORD='123456,master_auto_position=1;

 

使用root用户不需要创建用户,直接使用即可:

在从节点执行change命令:

stop slave;
CHANGE MASTER TO MASTER_HOST='192.168.217.16',MASTER_PORT=3311,MASTER_USER='root',MASTER_PASSWORD='123456,master_auto_position=1;

三,

启动slave

在从节点启动slave并查看slave的状态(这里最好是使用MySQL的cmd命令,Navicat查看的话,结果会很长,不利于观察):

start slave;
show slave status \G;

正确的输出应该是这样的;

MySQL [(none)]> show slave status \G;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    11
Current database: *** NONE ***
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.217.16
                  Master_User: root
                  Master_Port: 3311
                Connect_Retry: 60
              Master_Log_File: mysql_binlog.000013
          Read_Master_Log_Pos: 194
               Relay_Log_File: node3-relay-bin.000014
                Relay_Log_Pos: 413
        Relay_Master_Log_File: mysql_binlog.000013
             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: 194
              Relay_Log_Space: 879
              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: ca9907c5-5dd3-11ed-9029-000c29320c0d:1-19
            Executed_Gtid_Set: ae4751af-5d31-11ed-8ed7-000c29701212:1-3,
ca9907c5-5dd3-11ed-9029-000c29320c0d:1-22
                Auto_Position: 1
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 
1 row in set (0.01 sec)

可以看到有两个YES,表示主从复制状态正常,如果有错误, Last_IO_Error和Last_SQL_Error将会有日志,根据日志排查即可。

四,

测试环节

执行查询语句,可以看到各个节点都有一个表gtid_executed,此表内持久化存储了所有的GTID

select * from mysql.gtid_executed;

例如,从节点的17服务器,执行以上查询的结果:

             

master节点的查询结果:

slave节点出现的错误:

             Last_SQL_Error: Error 'Can't drop database 'mytest'; database doesn't exist' on query. Default database: 'mytest'. Query: 'drop database mytest'

解决方案:

停止slave,登陆从节点,新建数据库mytest,在启动slave。

附一:

主从复制的重置

如果主从复制出现错误,从 Last_IO_Error和Last_SQL_Error中找到的日志并不能解决错误的话,那么,重置主从复制是一个比较快速的方式。

  • RESET MASTER

删除所有index file 中记录的所有binlog 文件,将日志索引文件清空,创建一个新的日志文件,这个命令通常仅仅用于第一次用于搭建主从关系的时的主库,

注意

 reset master 不同于purge binary log的两处地方

1 reset master 将删除日志索引文件中记录的所有binlog文件,创建一个新的日志文件 起始值从000001 开始,然而purge binary log 命令并不会修改记录binlog的顺序的数值。

2 reset master 不能用于有任何slave 正在运行的主从关系的主库。因为在slave 运行时刻 reset master 命令不被支持,reset master 将master 的binlog从000001 开始记录,slave 记录的master log 则是reset master 时主库的最新的binlog,从库会报错无法找的指定的binlog文件,因此,在执行此命令的时候,所有的slave需要停止。

  • RESET SLAVE

reset slave 将使slave 忘记主从复制关系的位置信息。该语句将被用于干净的启动, 它删除master.info文件和relay-log.info 文件以及所有的relay log 文件并重新启用一个新的relaylog文件。

使用reset slave之前必须使用stop slave 命令将复制进程停止。

注 所有的relay log将被删除不管他们是否被SQL thread进程完全应用(这种情况发生于备库延迟以及在备库执行了stop slave 命令),存储复制链接信息的master.info文件将被立即清除,如果SQL thread 正在复制临时表的过程中,执行了stop slave ,并且执行了reset slave,这些被复制的临时表将被删除。

  • RESET SLAVE  ALL

在 5.6 版本中 reset slave 并不会清理存储于内存中的复制信息比如  master host, master port, master user, or master password,也就是说如果没有使用change master 命令做重新定向,执行start slave 还是会指向旧的master 上面。

当从库执行reset slave之后,将mysqld shutdown 复制参数将被重置。

在5.6.3 版本以及以后 使用使用 RESET SLAVE ALL 来完全的清理复制连接参数信息。

附二,

关于两个文件的持久化

在MySQL 5.6.2之前,slave记录的master信息以及slave应用binlog的信息存放在文件中,即master.info与relay-log.info,5.6.2版本之后,可以将这两个文件持久化到数据库内

对应的表分别为mysql.slave_master_info与mysql.slave_relay_log_info,且这两个表均为innodb引擎表。

数据库主配置文件mysqld字段内添加这两个参数(先停止slave,在添加下面的参数,然后重启MySQL服务):

master-info-repository  = TABLE    
relay-log-info-repository = TABLE  

可以看到,添加这两个参数后,在从节点可以查看到此表不是空的了,里面存储了master信息以及slave应用binlog的信息,例如:

select * from mysql.slave_master_info;

设置relay_log_info_repository和master_info_repository设置为TABLE可以提高数据库本身或者所在主机意外终止之后crash recovery的能力(这两张表是innodb表,可以保证crash之后表中的位置信息不丢失),且可以保证数据一致性,算是一个小优化吧。

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
4月前
|
资源调度 Kubernetes 调度
从单集群到多集群的快速无损转型:ACK One 多集群应用分发
本文介绍如何利用阿里云的分布式云容器平台ACK One的多集群应用分发功能,结合云效CD能力,快速将单集群CD系统升级为多集群CD系统。通过增加分发策略(PropagationPolicy)和差异化策略(OverridePolicy),并修改单集群kubeconfig为舰队kubeconfig,可实现无损改造。该方案具备多地域多集群智能资源调度、重调度及故障迁移等能力,帮助用户提升业务效率与可靠性。
|
4月前
|
资源调度 Kubernetes 调度
从单集群到多集群的快速无损转型:ACK One 多集群应用分发
ACK One 的多集群应用分发,可以最小成本地结合您已有的单集群 CD 系统,无需对原先应用资源 YAML 进行修改,即可快速构建成多集群的 CD 系统,并同时获得强大的多集群资源调度和分发的能力。
131 9
|
6月前
|
存储 Kubernetes 开发工具
使用ArgoCD管理Kubernetes部署指南
ArgoCD 是一款基于 Kubernetes 的声明式 GitOps 持续交付工具,通过自动同步 Git 存储库中的配置与 Kubernetes 集群状态,确保一致性与可靠性。它支持实时同步、声明式设置、自动修复和丰富的用户界面,极大简化了复杂应用的部署管理。结合 Helm Charts,ArgoCD 提供模块化、可重用的部署流程,显著减少人工开销和配置错误。对于云原生企业,ArgoCD 能优化部署策略,提升效率与安全性,是实现自动化与一致性的理想选择。
240 0
|
5月前
|
存储 Kubernetes 异构计算
Qwen3 大模型在阿里云容器服务上的极简部署教程
通义千问 Qwen3 是 Qwen 系列最新推出的首个混合推理模型,其在代码、数学、通用能力等基准测试中,与 DeepSeek-R1、o1、o3-mini、Grok-3 和 Gemini-2.5-Pro 等顶级模型相比,表现出极具竞争力的结果。
|
6月前
|
存储 Kubernetes 监控
K8s集群实战:使用kubeadm和kuboard部署Kubernetes集群
总之,使用kubeadm和kuboard部署K8s集群就像回归童年一样,简单又有趣。不要忘记,技术是为人服务的,用K8s集群操控云端资源,我们不过是想在复杂的世界找寻简单。尽管部署过程可能遇到困难,但朝着简化复杂的目标,我们就能找到意义和乐趣。希望你也能利用这些工具,找到你的乐趣,满足你的需求。
539 33
|
6月前
|
Kubernetes 开发者 Docker
集群部署:使用Rancher部署Kubernetes集群。
以上就是使用 Rancher 部署 Kubernetes 集群的流程。使用 Rancher 和 Kubernetes,开发者可以受益于灵活性和可扩展性,允许他们在多种环境中运行多种应用,同时利用自动化工具使工作负载更加高效。
315 19
|
Kubernetes 开发者 微服务
简化Kubernetes应用部署工具-Helm之Hook
本文讲的是简化Kubernetes应用部署工具-Helm之Hook【编者的话】微服务和容器化给复杂应用部署与管理带来了极大的挑战。Helm是目前Kubernetes服务编排领域的唯一开源子项目,做为Kubernetes应用的一个包管理工具,可理解为Kubernetes的apt-get / yum,由Deis 公司发起,该公司已经被微软收购。
2688 0
|
6月前
|
人工智能 分布式计算 调度
打破资源边界、告别资源浪费:ACK One 多集群Spark和AI作业调度
ACK One多集群Spark作业调度,可以帮助您在不影响集群中正在运行的在线业务的前提下,打破资源边界,根据各集群实际剩余资源来进行调度,最大化您多集群中闲置资源的利用率。
|
9月前
|
Prometheus Kubernetes 监控
OpenAI故障复盘 - 阿里云容器服务与可观测产品如何保障大规模K8s集群稳定性
聚焦近日OpenAI的大规模K8s集群故障,介绍阿里云容器服务与可观测团队在大规模K8s场景下我们的建设与沉淀。以及分享对类似故障问题的应对方案:包括在K8s和Prometheus的高可用架构设计方面、事前事后的稳定性保障体系方面。
|
6月前
|
Prometheus Kubernetes 监控
OpenAI故障复盘丨如何保障大规模K8s集群稳定性
OpenAI故障复盘丨如何保障大规模K8s集群稳定性
193 0
OpenAI故障复盘丨如何保障大规模K8s集群稳定性

推荐镜像

更多