草庐IT

带你走进MySQL全新高可用解决方案-MGR

vivo互联网 2023-03-28 原文

​一、初识MGR

相信很多人对MGR这个词比较陌生,其实MGR(全称 MySQL Group Replication 【MySQL 组复制】)是Oracle MySQL于2016年12月发布MySQL 5.7.17推出的一个全新高可用和高扩展的解决方案。具备以下特性:

  • 高一致性,基于原生复制及Paxos协议的组复制技术,并以插件的方式提供,提供一致数据安全保证;

  • 高容错性,只要不是大多数节点坏掉就可以继续工作,有自动检测机制,当不同节点产生资源争用冲突时,不会出现错误,按照先到者优先原则进行处理,并且内置了自动化脑裂防护机制;

  • 高扩展性,节点的新增和移除都是自动的,新节点加入后,会自动从其他节点上同步状态,直到新节点和其他节点保持一致,如果某节点被移除了,其他节点自动更新组信息,自动维护新的组信息;

  • 高灵活性,有单主模式(图1)和多主模式(图2),单主模式下,会自动选主,所有更新操作都在主上进行;多主模式下,所有server都可以同时处理更新操作。

单主模式(图1)

多主模式(图2)

MGR架构图如下所示:主要包括APIs层,组件层,负责协议模块和API+Paxos引擎层构成。

二、MGR技术演进

2.1 主从复制

传统MySQL复制默认提供了一种简单的主从复制方法,这种架构有一个主,以及一个或者多个从,当主节点执行提交事务,然后异步的方式发送到其他从节点,从库重新执行relay log日志内容达到主副本一致的目的,在默认情况下集群所有节点数据都是一致的。

MySQL异步复制

2.2  半同步复制

异步复制存在一定的数据丢失风险,MySQL又在5.6版本中推出半同步复制,在同步数据协议中添加了一个同步操作,这样意味主节点在commit操作,需要确认最少一个从节点确认接收到并且返回ACK,只有这样主节点才能正确提交数据。

MySQL半同步复制

2.3  组复制

MySQL MGR 集群最少3个server节点共同组成的分布式集群,一种share-nothing复制方案,每个server节点都有完整的副本。

MySQL组复制协议

三、MGR技术特性

3.1 故障检测

组复制自带提供一种故障检测机制,这个机制能报告哪个组成员是无响应的,并且如何判断该成员是否排除集群组。在组复制中故障检测是一种分布式服务。假设服务器A在预定时间段内未收到来自服务器B的消息,如果组内其他成员也同样未收到来自服务器B的消息,那么确认判断B发生故障,这样由其他成员判定将失联组成员从集群中剔除。

此时服务器B与其他服务节点都无法联系。由于无法达成最小仲裁成员数,处于独立状态,无法对外提供服务。

3.2 容错

MySQL组复制构建在Paxos分布式算法基础上实现的,以提供不同server之间的分布式协调。因此,它需要大多数server处于活动状态以达到仲裁成员数,从而做出决定。这对系统可以容忍的不影响其自身及其整体功能的故障数量有直接影响。容忍f个故障所需的server数量(n)n = 2 * f + 1。

实践中,这意味着为了容忍一个故障,组必须有三个server。如果一个服务器故障, 仍然有两个服务器形成大多数(三分之二)来允许系统自动地继续运行。但是,如果第二个server意外地宕掉,则该组锁定(只有一个server),因为没有达到多数可以达成选举(不能自己选举自己)。以下是说明上述公式的小表:

3.3  成员管理

组复制以组视图(Group View,后续简称视图)为基础来进行成员管理,视图一般在Group在一段时间内的成员状态,如果这段时间没有成员变化,也就是说没有成员的加入和退出,一旦有成员加入或者退出组,则视图就发生变化,并且使用视图ID(view id)进行跟踪变化区分先后时间,下面我们来看一张图演示一下:

序号部分,初始化时,第一个视图的序号从1开始,成员只有引导主一个,为进行初始化节点,以后出现的任何成员的加入和退出这个序号都需要增加1,可以通过performance_schema系统库下的replication_group_member_stats表中查询当前视图。

四、MGR安装体验

了解任何一个新技术从部署开始,安装比较简单,我们准备如下测试节点:

10.10.1.214

10.10.1.217

10.10.6.91

安装版本均为最新版本8.0.24,将安装包解压后进行初始化:

su - mysql wget http://mirrors.ustc.edu.cn/mysql-ftp/Downloads/MySQL-8.0/mysql-8.0.24-linux-glibc2.12-x86_64.tar tar -xf mysql-8.0.24-linux-glibc2.12-x86_64.tar cd mysql-8.0.24-linux-glibc2.12-x86_64 # 创建配置文件和数据目录 mkdir conf data 初始化数据库并且启动 ./bin/mysqld --initialize --datadir=/home/mysql/mysql-8.0.24-linux-glibc2.12-x86_64/data --basedir=/home/mysql/mysql-8.0.24-linux-glibc2.12-x86_64 ./bin/mysqld_safe --defaults-file=conf/my.cnf &

4.1  通用配置说明

配置代码

[mysqld] bind-address=0.0.0.0 datadir=/home/mysql/mysql-8.0.24-linux-glibc2.12-x86_64/data basedir=/home/mysql/mysql-8.0.24-linux-glibc2.12-x86_64 port=3306 socket=/home/mysql/mysql-8.0.24-linux-glibc2.12-x86_64/data/mysqld.sock user=mysql # 每个节点要求不一样 server_id=1 gtid_mode=ON enforce_gtid_consistency=ON master_info_repository=TABLE relay_log_info_repository=TABLE binlog_checksum=NONE log_slave_updates=ON log_bin=binlog binlog_format=ROW innodb_buffer_pool_size=1g # 8.0 默认值XXHASH64,针对写事务进行哈希处理 transaction_write_set_extraction=XXHASH64 # 启动加载组复制插件 plugin_load_add='group_replication.so' # 集群唯一ID group_replication_group_name="8d3cebd8-b132-11eb-8529-0242ac130003" # 是否启动MySQL服务时启动组复制,建议值:off group_replication_start_on_boot=off # 本地IP后面端口33061可自定义,集群通信端口,建议统一端口 group_replication_local_address= "10.10.1.214:33061" # 初始化集群成员列表,可动态修改 group_replication_group_seeds= "10.10.1.214:33061,10.10.1.217:33061,10.10.6.91:33061" # 判断是否为引导组 group_replication_bootstrap_group=off # 设置白名单,这里特别注意,如果是同网段可以不用设置,如果是不同网段则需要修改否则通信端口不可访问 loose-group_replication_ip_whitelist='10.10.1.214,10.10.1.217,10.10.6.91'

4.2  单主模式部署

4.2.1  引导节点初始化

# 创建用户和安装插件 mysql> SET SQL_LOG_BIN=0; Query OK, 0 rows affected (0.00 sec) mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'password'; Query OK, 0 rows affected (0.01 sec) mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%'; Query OK, 0 rows affected (0.00 sec) mysql> GRANT BACKUP_ADMIN ON *.* TO rpl_user@'%'; Query OK, 0 rows affected (0.00 sec) mysql> FLUSH PRIVILEGES; Query OK, 0 rows affected (0.00 sec) mysql> SET SQL_LOG_BIN=1; Query OK, 0 rows affected (0.00 sec) mysql> CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_user', SOURCE_PASSWORD='password' FOR CHANNEL 'group_replication_recovery'; Query OK, 0 rows affected, 2 warnings (0.05 sec) mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so'; mysql> SHOW PLUGINS; +---------------------------------+----------+--------------------+----------------------+---------+ | Name | Status | Type | Library | License | +---------------------------------+----------+--------------------+----------------------+---------+ | group_replication | ACTIVE | GROUP REPLICATION | group_replication.so | GPL | +---------------------------------+----------+--------------------+----------------------+---------+ # 启动引导节点 mysql> SET GLOBAL group_replication_bootstrap_group=ON; Query OK, 0 rows affected (0.00 sec) mysql> START GROUP_REPLICATION; Query OK, 0 rows affected, 1 warning (2.33 sec) mysql> SET GLOBAL group_replication_bootstrap_group=OFF; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM performance_schema.replication_group_members; +---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+ | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | +---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+ | group_replication_applier | 4cf69361-b22b-11eb-a2c9-fa163ebefc6a | 10-10-1-214 | 3306 | ONLINE | PRIMARY | 8.0.24 | +---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+

4.2.2  加入从节点

mysql> SET SQL_LOG_BIN=0; Query OK, 0 rows affected (0.00 sec) mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'password'; Query OK, 0 rows affected (0.01 sec) mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%'; Query OK, 0 rows affected (0.03 sec) mysql> GRANT BACKUP_ADMIN ON *.* TO rpl_user@'%'; Query OK, 0 rows affected (0.00 sec) mysql> FLUSH PRIVILEGES; Query OK, 0 rows affected (0.00 sec) mysql> SET SQL_LOG_BIN=1; Query OK, 0 rows affected (0.00 sec) mysql> CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_user', SOURCE_PASSWORD='password' FOR CHANNEL 'group_replication_recovery'; Query OK, 0 rows affected, 2 warnings (0.05 sec) mysql> START GROUP_REPLICATION; Query OK, 0 rows affected, 1 warning (3.33 sec) # 检查状态 mysql> SELECT * FROM performance_schema.replication_group_members; +---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+ | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | +---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+ | group_replication_applier | 4cf69361-b22b-11eb-a2c9-fa163ebefc6a | 10-10-1-214 | 3306 | ONLINE | PRIMARY | 8.0.24 | | group_replication_applier | 53f39dba-b22b-11eb-bfdb-fa163e42784d | 10-10-1-217 | 3306 | ONLINE | SECONDARY | 8.0.24 | +---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+ 2 rows in set (0.00 sec) 其他一个节点执行上述即可,执行完成后检查 mysql> SELECT * FROM performance_schema.replication_group_members; +---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+ | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | +---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+ | group_replication_applier | 4cf69361-b22b-11eb-a2c9-fa163ebefc6a | 10-10-1-214 | 3306 | ONLINE | PRIMARY | 8.0.24 | | group_replication_applier | 53f39dba-b22b-11eb-bfdb-fa163e42784d | 10-10-1-217 | 3306 | ONLINE | SECONDARY | 8.0.24 | | group_replication_applier | 56779526-b22b-11eb-a28e-fa163e1f9809 | 10-10-6-91 | 3306 | ONLINE | SECONDARY | 8.0.24 | +---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+ 3 rows in set (0.00 sec)

4.3  多主模式部署

多主模式和单主部署方式差不多,只在加入集群时多执行:

set global group_replication_single_primary_mode=off; 单主的都是ON。

4.3.1  引导节点初始化

mysql> set global group_replication_single_primary_mode=off; Query OK, 0 rows affected (0.00 sec) mysql> SET GLOBAL group_replication_bootstrap_group=ON; Query OK, 0 rows affected (0.00 sec) mysql> start group_replication; Query OK, 0 rows affected, 1 warning (2.16 sec) mysql> SET GLOBAL group_replication_bootstrap_group=OFF; Query OK, 0 rows affected (0.00 sec) mysql> select * from performance_schema.replication_group_members; +---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+ | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | +---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+ | group_replication_applier | 4cf69361-b22b-11eb-a2c9-fa163ebefc6a | 10-10-1-214 | 3306 | ONLINE | PRIMARY | 8.0.24 | +---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+ 1 row in set (0.00 sec)

4.3.2  加入其他节点

mysql> set global group_replication_single_primary_mode=off; Query OK, 0 rows affected (0.00 sec) mysql> START GROUP_REPLICATION; Query OK, 0 rows affected, 1 warning (3.26 sec) mysql> select * from performance_schema.replication_group_members; +---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+ | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | +---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+ | group_replication_applier | 4cf69361-b22b-11eb-a2c9-fa163ebefc6a | 10-10-1-214 | 3306 | ONLINE | PRIMARY | 8.0.24 | | group_replication_applier | 53f39dba-b22b-11eb-bfdb-fa163e42784d | 10-10-1-217 | 3306 | ONLINE | PRIMARY | 8.0.24 | | group_replication_applier | 56779526-b22b-11eb-a28e-fa163e1f9809 | 10-10-6-91 | 3306 | ONLINE | PRIMARY | 8.0.24 | +---------------------------+--------------------------------------+-------------------------------------------------+-------------+--------------+-------------+----------------+ 3 rows in set (0.00 sec)

4.4  测试体验

# 在任意节点执行 mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 4 rows in set (0.00 sec) mysql> create database test; Query OK, 1 row affected (0.01 sec) # 任意节点查询 mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | | test | +--------------------+ 5 rows in set (0.00 sec)

五、应用场景

  • MGR采用多副本模式,在2N+1个集群中,集群只要N+1个节点还存活,数据库就能稳定对外提供服务,适用于金融场景,因为这些场景数据必须零丢失,可用性在4个9甚至5个9。

  • 适用于替代当前主从高可用版本,解决单点写入问题。

  • 针对业务需要弹性扩展节点的基础架构环境,例如私有云。

六、总结

尽管MySQL在2016年就推出了MGR该功能,同时我们也知道有很多好处,并且有大胆的公司采用进行测试甚至部署线上环境,据公开资料网易、滴滴都有使用,国内部分商业银行也有使用,但仍然有不少人处于观望状态,主要有以下几点原因导致:

需求不是特别强烈

  • 很多业务情况使用MySQL半同步和异步复制足够满足业务要求,配合MHA第三方组件满足了绝大部分场景需求。
分布式新事物

  • 本身分布式这个概念已经存在多年,但是由于MGR推出年限较短,且我们搜索官方bug库任然存在较多未解决的bug。用户使用排查问题较为困难,且由于分布式设计导致问题复现难也是一种阻碍。
生态不成熟

  • 官方几乎没有完全成熟用来构建整套高可用架构的解决方案,如果想要大规模使用还是需要更加成熟的生态。
任何新鲜事物都有一个被大众接受过程,只是需要时间筛选和磨砺。

参考文档

https://dev.mysql.com/doc/refman/8.0/en/group-replication.html

作者:vivo互联网数据库团队-Liu Shilin

有关带你走进MySQL全新高可用解决方案-MGR的更多相关文章

  1. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

    在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

  2. ruby-on-rails - 如何使辅助方法在 Rails 集成测试中可用? - 2

    我在app/helpers/sessions_helper.rb中有一个帮助程序文件,其中包含一个方法my_preference,它返回当前登录用户的首选项。我想在集成测试中访问该方法。例如,这样我就可以在测试中使用getuser_path(my_preference)。在其他帖子中,我读到这可以通过在测试文件中包含requiresessions_helper来实现,但我仍然收到错误NameError:undefinedlocalvariableormethod'my_preference'.我做错了什么?require'test_helper'require'sessions_hel

  3. 屏幕录制为什么没声音?检查这2项,轻松解决 - 2

    相信很多人在录制视频的时候都会遇到各种各样的问题,比如录制的视频没有声音。屏幕录制为什么没声音?今天小编就和大家分享一下如何录制音画同步视频的具体操作方法。如果你有录制的视频没有声音,你可以试试这个方法。 一、检查是否打开电脑系统声音相信很多小伙伴在录制视频后会发现录制的视频没有声音,屏幕录制为什么没声音?如果当时没有打开音频录制,则录制好的视频是没有声音的。因此,建议在录制前进行检查。屏幕上没有声音,很可能是因为你的电脑系统的声音被禁止了。您只需打开电脑系统的声音,即可录制音频和图画同步视频。操作方法:步骤1:点击电脑屏幕右下侧的“小喇叭”图案,在上方的选项中,选择“声音”。 步骤2:在“声

  4. 【高数】用拉格朗日中值定理解决极限问题 - 2

    首先回顾一下拉格朗日定理的内容:函数f(x)是在闭区间[a,b]上连续、开区间(a,b)上可导的函数,那么至少存在一个,使得:通过这个表达式我们可以知道,f(x)是函数的主体,a和b可以看作是主体函数f(x)中所取的两个值。那么可以有,  也就意味着我们可以用来替换 这种替换可以用在求某些多项式差的极限中。方法: 外层函数f(x)是一致的,并且h(x)和g(x)是等价无穷小。此时,利用拉格朗日定理,将原式替换为 ,再进行求解,往往会省去复合函数求极限的很多麻烦。使用要注意:1.要先找到主体函数f(x),即外层函数必须相同。2.f(x)找到后,复合部分是等价无穷小。3.要满足作差的形式。如果是加

  5. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  6. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  7. ruby-on-rails - 无法安装 mysql2 0.3.14 gem - 2

    我看到其他人也遇到过类似的问题,但没有一个解决方案对我有用。0.3.14gem与其他gem文件一起存在。我已经完全按照此处指示完成了所有操作:https://github.com/brianmario/mysql2.我仍然得到以下信息。我不知道为什么安装程序指示它找不到include目录,因为我已经检查过它存在。thread.h文件存在,但不在ruby​​目录中。相反,它在这里:C:\RailsInstaller\DevKit\lib\perl5\5.8\msys\CORE\我正在运行Windows7并尝试在Aptana3中构建我的Rails项目。我的Ruby是1.9.3。$gemin

  8. Ruby 守护进程和 JRuby - 备选方案 - 2

    我有一个应用程序正在从Ruby迁移到JRuby(由于需要通过Java提供更好的Web服务安全支持)。我使用的gem之一是daemons创建后台作业。问题在于它使用fork+exec来创建后台进程,但这对JRuby来说是禁忌。那么-是否有用于创建后台作业的替代gem/wrapper?我目前的想法是只从shell脚本调用rake并让rake任务永远运行......提前致谢,克里斯。更新我们目前正在使用几个与Java线程相关的包装器,即https://github.com/jmettraux/rufus-scheduler和https://github.com/philostler/acts

  9. ruby - 如何更快地解决 project euler #21? - 2

    原始问题Letd(n)bedefinedasthesumofproperdivisorsofn(numberslessthannwhichdivideevenlyinton).Ifd(a)=bandd(b)=a,whereab,thenaandbareanamicablepairandeachofaandbarecalledamicablenumbers.Forexample,theproperdivisorsof220are1,2,4,5,10,11,20,22,44,55and110;therefored(220)=284.Theproperdivisorsof284are1,2,

  10. ruby - 如何使用 ruby​​ mysql2 执行事务 - 2

    我已经开始使用mysql2gem。我试图弄清楚一些基本的事情——其中之一是如何明确地执行事务(对于批处理操作,比如多个INSERT/UPDATE查询)。在旧的ruby-mysql中,这是我的方法:client=Mysql.real_connect(...)inserts=["INSERTINTO...","UPDATE..WHEREid=..",#etc]client.autocommit(false)inserts.eachdo|ins|beginclient.query(ins)rescue#handleerrorsorabortentirelyendendclient.commi

随机推荐