MySQL数据库TDSQL架构分析及采用策略扩容流程

2023-11-11

2016-10-14 22:16  401人阅读  评论(0)  收藏  编辑  删除
  分类:
随着业务的发展,基于内存的NoSQL解决方案HOLD平台在高峰期一天支撑3000亿读写,证明了分布式Cache的巨大价值;但随着各种业务的接入,NoSQL方案的不足也逐步显现出来了,如下所示。 

1.适用的业务场景比较有限,仅提供get/set操作,有不少业务场景希望能通过记录中的其他字段做索引来查询,比如流水类业务。 
2.不是所有的数据都是热点,一台64GB内存机器提供的有效内存空间大概在50GB左右,而采用Fusion卡的机型容量一般在1TB以上,对比起来,如果所有数据放入分布式Cache明显是一种极大的浪费,最合理的当然是热点在HOLD,冷数据采用基于磁盘的存储。 
3.计费平台部多年来在支付领域有了相当多的技术积累,HOLD作为NoSQL系统功能有限,因此建造一套更加强大通用的高一致性存储系统将整个支付领域的实时数据(重点是账户数据、用户订单数据,以及海量的流水数据)统一管理起来非常有价值。 
基于上面的分析,结合我们在MySQL领域多年的应用和优化经验,最终决定在MySQL存储引擎基础之上,打造一套分布式的SQL系统。 

1.保持原来的MySQL协议,这样以前访问MySQL系统的C++、Java各类系统都不需要修改,DBA能继续保持原来大部分使用习惯。 
2.自动的跨IDC容灾切换,同时保证数据一致性,对于提交成功的事务保证一笔不丢,达到银行级对容灾的要求。 
3.灵活的容量伸缩机制,对业务透明,解决MySQL本身扩容不灵活的问题。 
4.重点支持OLTP类型的在线业务。 
整体架构 

针对上面的需求,TDSQL最终的结构如图1所示(与当前大部分中心化的分布式系统类似)。 

 

图1 TDSQL架构

系统由三个模块组成:Scheduler、Agent、网关,三个模块的交互都是通过ZooKeeper完成,极大简化了各个节点之间的通信机制,相对于第二代HOLD的开发简单了很多。 

Scheduler作为集群的管理调度中心,主要功能包括: 

1.管理set,提供创建、删除set、set内节点替换等工作; 
2.所有的DDL操作统一下发和调度; 
3.监控set内各个节点的存活状态,当set内主节点故障,发起高一致性主备切换流程; 
4.监控各个set的CPU、磁盘容量、各个表的资源消耗情况,必要的时候自动发起扩容流程; 
5.Scheduler自身的容灾通过ZooKeqzer的选举机制完成,保证中心控制节点无单点。 
Agent模块负责监控本机MySQL实例的运行情况,主要功能包括: 
1.用短连接的方式周期性访问本机的MySQL实例,检测是否可读、可写,若发生异常,会将异常信息上报到ZooKeeper,最终会由上面描述的Scheduler模块检测到这个异常情况,从而发起容灾切换; 
2.检测主备复制的执行情况,会定期上报主备复制的延时和延迟的事务数,若发生了主备切换,自动向新主机重建主备,因此MySQL的主备不需要DBA干预,对于新增的实例会3.自动采用xtrabackup通过主机自动重建数据; 
4.检测MySQL实例的CPU利用率和各个表的请求量、数据量、CPU利用率,上报到ZooKeeper,ZooKeeper通过全局的资源情况抉择如何扩容、缩容; 
5.监控是否有下发到自身的扩容任务,如有则会执行扩容流程(下面会有描述); 
监控是否要发生容灾切换,并按计划执行主备切换流程。 

网关基于MySQL Proxy开发,在网络层、连接管理、SQL解析、路由等方面做了大量优化,主要特点和功能如下: 

1.解析SQL,将识别出的DDL语句直接存到ZooKeeper,让Keeper来统一调度; 
2.Watch ZooKeeper的路由信息,拉取最新的路由表保存到本地文件和内存; 
3.将SQL请求路由到对应的set,支持读写分离; 
4.对接入的IP、用户名、密码进行鉴权; 
5.记录完整的SQL执行信息,与秒级监控平台对接完成实时的SQL请求的时耗,成功率等指标监控分析; 
6.对count、distinct、sum、avg、max、min、order by、group by等聚合类SQL一般需要访问后端的多个set,网关会分析结果并做合并再返回,暂不支持跨set join和分布式事务; 
7.网关无状态,既支持与业务部署到一起,也可以独立部署(可通过TGW或者LVS做容灾)。 

自动扩容机制 

目前,针对MySQL的扩容,一般有下面两种策略。 

1.垂直扩容。一般通过升级硬件来实现,比如更换更好的CPU,将传统的sas盘换成FusionIO卡这类,然后针对新硬件调整好参数,在硬件结构变化比较大的时候,性能甚至能达到上十倍的提升。但垂直扩容有比较大的局限,就是这种模式随着业务的突增还是比较容易达到瓶颈,特别是面对互联网海量用户的时候,所以在互联网应用场景下,一般仅将垂直扩容当做一个辅助的手段。 
2.水平扩容。常用的有2种方法,一是不同的库或者表部署到不同的实例,二是一张表需要根据某个字段拆分到不同的字表中(数据分片),这种策略在互联网系统中非常常见,很多系统会将这2种水平扩容的方法结合起来使用; 
通过上述2种扩容方法的比较,为了应对海量扩展的需求,应该是重点选用水平扩容的方法。但水平扩容的实现一般对业务是有感知的,比如采用什么规则来拆表,拆开的表放到哪些节点,如果某个子表还有瓶颈应该怎么扩容,扩容是否还需要业务配合等等这些事情如果全部交给业务会比较繁琐,因此这些需求应该尽量全部交给TDSQL自身来完成,对业务完全透明。 

分表逻辑 

在TDSQL中,每个表(逻辑表)可能会拆分成多个子表(建表的时候通过在建表语句中嵌入注释的方式提供一个shard字段名,最多会拆分出1W个子表),每个子表在MySQL上都是一个真实的物理表,这里称为一个shard,因此一张表的数据可能会按这样的方式分布在多个Set中,如图2所示 

 

每个SQL请求到达网关之后,网关会做词法和语法解析,重点会解析出shard字段,如果带了shard字段就可以直接查询路由表并发送到某个具体的set中。计费的OLTP类业务99%的请求都会带上shard字段;如果某笔请求没有shard字段,查询路由之后会将请求发送到所有的shard对应的set中,并对所有返回的结果做一些聚合运算。 

扩容流程 

上面描述了shard的方式,但是这样的shard结构不是固定不变的,当Scheduler检测到某个set,某个表的CPU、磁盘超过阈值之后就会启动扩容流程。 

这里描述下具体的扩容流程。 

扩容过程中一般都要尽量避免影响业务,目前来看存在2种比较成熟的策略。 

策略1先切后搬:先修改路由,将需要迁走的数据的请求直接发送到新set,在新set交易过程中如发现本地的数据不存在,则去原set拉取数据,然后再通过一些离线的策略将要迁移的数据全量再搬迁一次,HOID平台就是采用这样的策略。 

策略2先搬后切:让请求继续在原set交易,扩容程序首先记录一个binlog位置点,并将源set中符合迁移条件的数据全部迁移出去,最后再将搬迁过程中新增的binlog追完,最后修改路由规则,将请求发送到新set。 

综合来看,策略1最大的优点是假如是因为压力大做的迁移,可能很快就能将部分请求发送新set了,实现对原set的压力分担;策略2实现上在最后的追路由阶段需要更多的精细化控制,实现会稍微复杂点,但策略2有个非常大的好处就是扩容过程中回滚非常方便,如有异常直接干掉扩容任务即可。 

对于TDSQL这类数据库业务系统来说,策略1实现会非常麻烦,因为请求到达新set之后可能需要去源set拉取数据,这个需要对MySQL本身进行修改;另外假如一个批量更新的update操作,可能要往新老set都发送一次请求,比较复杂,所以最终选择了策略2。策略2会有更大的通用性,开发模式基本上可以统一到所有类似的系统。 

下面时间财富网的小编描述采用策略2具体的扩容流程。假如要将Set1中的t_shard_1的数据迁移一半到Set4中的t_shard_4(1667-3333)。 

 

图3 策略2的扩容流程

Scheduler首先在Set4中创建好表t_shard_4。 

后将扩容任务下发到Set1中的agent模块,agent检测到扩容任务之后会采用mysqldump+where条件的方式将t_shard_1中shard号段为1667-3333的记录导出来并通过管道用并行的方式插入到Set4(不会在本地存文件,避免引起过多的IO),用mysqldump导出镜像的时候会有一个binlog位置。 

从mysqldump记录的binlog位置开始读取binlog并插入到到Set4,追到所有binlog文件末尾的时候(这需要一个循环,每次循环记录从开始追binlog截止到追到文件结尾消耗的时间,必须保证追单次循环要在几秒之内完成,避免遗留的binlog太多导致最后一次追binlog消耗太多的时间,从而影响业务过久),对原来的表t_shard_1重命名t_shard_5,此时针对这个表不会再有新请求,若还有请求过来都会失败,然后再追一次binlog到文件结尾(因为上面的循环保证了追binlog不会太耗时间了,所以此次会快速完成),然后上报状态到ZooKeeper,表明扩容任务完成。 

Scheduler收到扩容完成的信息之后会修改路由表,最后由网关拉取到新路由完成整体的扩容;从表重命名开始到网关拉取到新路由,这段时间这个原始shard不可用,从我们测试结果来看这个不可用的时间是200毫秒左右;如果某个网关异常,拉取不到新路由,继续访问老表t_shard_1会一直失败,这样就可以保证数据的一致性。 

容灾机制 

对于TDSQL来说,我们希望容灾做到自动切换,自动恢复,主备一致性(保证业务提交的事务在切换过程不丢失),跨IDC容灾。 

【MySQL异步复制】 

在MySQL发展的早期,就提供了异步复制的技术,只要写的压力不是特别大,在网络条件较好的情况下,发生主备切换基本上能将影响控制到秒级别,因此吸引了很多开发者的关注和使用。但这套方案提供的一致性保证,对于计费或者金融行业是不够的。 

图4是异步复制的大致流程,很显然主机提交了binlog就会返回给业务成功,没有保证binlog同步到了备机,这样在切换的瞬间很有可能丢失这部分事务。 

 

【MySQL半同步复制】 

到了MySQL 5.5版本的时候,Google提供了一个半同步半异步的插件,确保必须收到一个备机的应答才让事务在主机中提交;当备机应答超时的情况下,强同步就会自动退化成异步模式(这也是半同步半异步名字的由来)。 

 

图5 半同步复制


这套方案相对异步复制,在数据的可靠性方面确实好很多,在主机本身故障的情况下,基本能保证不丢失事务(因为最后一个事务,至少有一个备机上存在),但一旦退化成异步复制就回到过去了。TDSQL没直接采用这套方案,是因为:在主备跨IDC(ping延迟2-3毫秒)时性能非常很低。 
【Cluster方案】 

除了上面的方案外,开源社区还有三个Cluster解决方案,分别是Oracle的NDB引擎、Percona XtraDB Cluster和MariaDB Galera Cluster,从公开资料的性能对比上来看,后2者在性能和系统灵活性等方面都强于NDB(同时采用NDB意味着也放弃了InnoDB引擎,NDB主要是基于全内存的,并且需要高速网络环境支持,所以不考虑了);Percona XtraDB Cluster和MariaDB Galera Cluster强同步机制的底层都是采用Galera这套强同步的架构。MariaDB Galera Cluster具有如下非常吸引人的特性: 

1.MariaDB Galera Cluster 是一套在MySQL InnoDB存储引擎上面实现multi-master及数据实时同步的系统架构,业务层面无需做读写分离工作,数据库读写压力都能按照既定的规则分发到各个节点上去; 
2.同步复制Synchronous replication:保证节点间数据一致性; 
3.Active-active multi-master拓扑逻辑:多主的拓扑结构,可以认为没有备机的概念; 
4.可对集群中任一节点进行数据读写:假如一个set有3个节点,则3个节点可以同时读写,上次完全不用关心主备切换和读写分离; 
5.自动成员控制,故障节点自动从集群中移除; 
6.自动节点加入; 
7.真正并行的复制,基于行级:同一个表可以在集群中任何节点更新,支持不带where条件,但一次更新的记录条数有限制; 
8.每个节点都包含完整的数据副本。 
目前来看,Galera是一套相当完美的方案。但是,在跨IDC的性能测试中,其性能下降比较大,另外,实现方案也比较复杂,目前对它的代码理解还不够透彻,所以暂时没有在计费领域大范围推广使用。但我相信这个方向是对的,有吸引力的,随着后续Galera越来越完善,我们对它研究得越透彻,也许有一天会采用这套方案。 

目前来看,Galera是一套相当完美的方案。但是,在跨IDC的性能测试中,其性能下降比较大,另外,实现方案也比较复杂,目前对它的代码理解还不够透彻,所以暂时没有在计费领域大范围推广使用。但我相信这个方向是对的,有吸引力的,随着后续Galera越来越完善,我们对它研究得越透彻,也许有一天会采用这套方案。 

【性能测试和分析】 

上面的三种复制模式对比测试,数据如图6所示。 

 

图6 三种复制模式的对比


从图6的数据可以看出,半同步和Galera模式对性能的损耗还是非常大的,Galera的毛刺尤其严重,所以在跨IDC环境下还不是适合计费这样对延迟要求非常低的场景。 

为什么性能损耗会这么严重呢?这个看明白MySQL的网络模型就清楚了。外界可查的MySQL最早的公开版本应该是1996年的3.1.1.1版本,这么多年来,网络模型基本上变化不大,与Apache有点类似,有点区别的是MySQL采用的是每个连接一个线程的模型,这套模型最大的好处就是开发特别简单,线程内部都是同步调用,只要不访问外部接口,支撑每秒几百上千的请求量也基本够用,因为大部分情况下IO是瓶颈。不过随着当前硬件的发展,尤其是SSD、FusionIO的出现,IOPS从200+/s进化到几十万甚至百万次/s,IO基本上不再是瓶颈,若再采用这套模型并采用阻塞的方式调用延迟较大的外部接口,则CPU都会阻塞在等网络应答上了,性能自然上不去。 

不过在MySQL5.6企业版和MariaDB、Percona中都引入了线程池,使得网络模型灵活了很多,图7是简化后的对比模型。 

 

图7 简化的对比模型


TDSQL采用的强同步方案 

从上面的分析可知,半同步半异步是比较轻量级的高一致性容灾方案,但受限于已有的同步网络模型,CPU利用不起来。我们如果在线程池基础之上做一些修改,参考半同步的思路就可以实现一个高性能的强同步方案。 

目前的做法是采用与Linux内核处理中断的思路:将上面线程池模型的第三个环节(执行SQL的逻辑)拆成两个部分: 

1.上半部分:任务执行到写binlog为止,然后将会话保存到session中,接着执行下一轮循环去处理其他请求了,这样就避免让线程阻塞等待应答了; 
2.然后:MySQL自身负责主备同步的dump线程会将binlog立即发送出去,备机的IO线程收到binlog并写入到relay log之后,再通过UDP给主机一个应答; 
3.在主机上,开一组线程来处理应答,收到应答之后找到对应的会话,执行下半部分的commit,send应答,绑定到epoll等操作。绑定到epoll之后这个连接又可以被其他线程检测到并执行了。 
改造后性能提升明显,如图8所示。 

 


数据高可用性保障机制 

除上述强同步机制外,TDSQL还做了以下增强,以提升数据的可用性。 

1.推荐一个set最少配置3个跨IDC的节点,可以按业务的要求对备机开放查询服务。 
2.支持灵活增加节点,比如觉得3个节点还不够,可以非常方便地增加节点。TDSQL会自动完成数据的全量和增量复制,此处主要依赖Xtrabackup实现物理复制,性能测试数据表明:一个小时大概可以拷贝500GB数据到新节点。那么对于Z3(1.1TB盘,一般最多用800GB左右),新加入的节点大概1.5个小时左右就有了全量数据,此功能也可以用在坏盘等情况下替换节点的时候使用,非常方便。 
3.细心的同学可能会发现上面的强同步还有点小缺陷:比如主机用kill -9杀掉,那么可能写了binlog但没有来得及发送到远端,此时当然也不会返回给业务成功,备机上不存在这笔数据,但主机起来之后会多出来这笔事务。我们的做法是对新增的事务根据row格式的binlog做闪回,当然回退不了的比如drop table之类的,就直接提醒运维手工确认是否清除数据库,然后会由Xtrabakcup机制自动从新的备机全量拉取数据重构。 
4.节点的监控通过跨IDC部署的ZooKeeper来保证,并且主备切换由一套自动化的严格流程来保证。 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MySQL数据库TDSQL架构分析及采用策略扩容流程 的相关文章

随机推荐

  • mybatis.type-aliases-package的作用和用法

    第一种在mapper xml文件中的resultMap的type或者parameterType会用到自定义的POJO 其中resultType User 中 User就是自定义的POJO 此时可以使用完全限定名来指定这些POJO的引用 第二
  • lambda 和 Predicate 的妙用示例

    1 过滤集合数据的多种常用方法 public class DemoTest1 public static void main String args List
  • 数据挖掘和机器学习之间,主要有什么区别和联系?

    数据挖掘和机器学习的区别和联系 周志华有一篇很好的论述 机器学习和数据挖掘 可以帮助大家理解 数据挖掘受到很多学科领域的影响 其中数据库 机器学习 统计学无疑影响最大 简言之 对数据挖掘而言 数据库提供数据管理技术 机器学习和统计学提供数据
  • 手势识别Python-OpenCV

    目录 一 选题背景 5 二 设计理念 5 2 1 搭建平台 5 2 2 问题描述 5 2 3 过程概述 6 三 过程论述 6 3 1 数据集生成 6 3 1 1 标准化图片的采集 6 3 1 2肤色检测 7 3 1 3 特征提取 8 3 1
  • Linux系统基础命令

    Linux系统常用基本命令 ls 查看当前目录下所有文件 注 蓝色 文件夹 白色 普通文件 绿色 拥有执行权限的文件 红色 压缩文件 touch 示例 touch filename txt 在当前目录下创建一个文件 注 文件名区分大小写 文
  • 【LeetCode】83. 删除排序链表中的重复元素

    83 删除排序链表中的重复元素 简单 方法 一次遍历 思路 由于给定的链表是排好序的 因此重复的元素在链表中出现的位置是连续的 因此我们只需要对链表进行一次遍历 就可以删除重复的元素 从指针 cur 指向链表的头节点 随后开始对链表进行遍历
  • 【时间序列数据挖掘】ARIMA模型

    目录 0 前言 一 移动平均模型MA 二 自回归模型AR 三 自回归移动平均模型ARMA 四 自回归移动平均模型ARIMA 总结 0 前言 传统时间序列分析模型 ARIMA模型是一个非常灵活的模型 对于时间序列的好多特征都能够进行描述 比如
  • MYSQL数据库测评及整改

    1 查询数据库版本 select version 2 查询已安装的插件 show plugins 3 查询插件安装的位置 show variables like plugin dir 4 查询用户 选择数据库 select host use
  • 阿里云OCR图片识别

    阿里云OCR图片识别 请求参数 Body 请求示例 java 正常返回示例 错误码定义 阿里云OCR图片识别 单字识别 表格识别 旋转功能 准备条件 阿里云OCR图片识别API购买 初次购买1分钱500次接口调用 请求参数 Body 图像数
  • Java多线程——为什么弃用stop、suspend、resume方法

    初始的Java版本定义了一个stop方法用来终止一个线程 以及一个suspend方法用来阻塞一个线程直至另一个线程调用resume stop和suspend方法有一些共同点 都试图控制一个给定线程的行为 stop suspend和resum
  • 利用Python写Api

    初学者 仅作笔记参考 因为没使用web框架 采用的原生sql进行数据查询有点呆板 from mysql Database import Demo from utils tools import Tools import flask json
  • 运行快捷指令_iOS 13 快捷指令无法运行的解决办法

    升级 iOS13 以后 快捷指令 App 也迎来全新版本 新设计的快捷指令 App 有诸多不同 尤其在权限控制上更为严格 这导致部分快捷指令打开时报错的问题 首次添加快捷指令规则后 运行时提示 无法打开 XXX 这个问题其实很容易解决 方法
  • linux 下 redis 设置密码

    在服务器上 这里以linux服务器为例 为redis配置密码 1 第一种方式 当前这种linux配置redis密码的方法是一种临时的 如果redis重启之后密码就会失效 1 首先进入redis 如果没有开启redis则需要先开启 root
  • matlab函数结果,从Matlab函数返回多个输出变量

    一些选择 添加一个参数以指定控制台的详细输出 但默认情况下将其设置为false function A B C test x y z verbose if nargin 3 verbose false end A 2 x B 2 y C 2
  • JavaScript基础--es6新增的数组方法

    今天给大家介绍一些es6新增的常用数组方法 1 映射数组 map 方法 目的 为了操作原数组 但不改变原数组的值 作用 map 方法返回一个新数组 数组中的元素为原始数组元素调用函数处理后的值 不会对空数组进行检测 返回值 新数组 一定和原
  • 欧拉角的理解

    1 欧拉角概念 百度百科 欧拉角 用来确定定点转动刚体位置的3个一组独立角参量 欧拉角由章动角 旋进角 即进动角 和自转角 组成 欧拉角为欧拉首先提出而得名 维基百科 Euler angles 莱昂哈德 欧拉用欧拉角来描述刚体在三维欧几里得
  • 【100%通过率 】【华为OD机试真题 c++/java】关联端口组合并【 2023 Q1

    华为OD机试 题目列表 2023Q1 点这里 2023华为OD机试 刷题指南 点这里 题目描述 有M 1 lt M lt 10 个端口组 每个端口组是长度为N 1 lt N lt 100 的整数数组 如果端口组间存在2个及以上不同端口相同
  • pycharm 退出scientific mode科学模式

    之前工作需要进入scientific mode将pycharm调成科学模式 后来使用bert模型发现一直报错 也没改动代码 困惑了大半天 偶然的机会 退出scientific mode发现不报错了 这里记录一下 我用的是pycharm社区版
  • 理解LSTM网络(翻译)

    Translated on December 19 2015 本文为博客 Understanding LSTM Networks 的翻译文章 原文链接 http colah github io posts 2015 08 Understan
  • MySQL数据库TDSQL架构分析及采用策略扩容流程

    MySQL数据库TDSQL架构分析及采用策略扩容流程 2016 10 14 22 16 401人阅读 评论 0 收藏 编辑 删除 分类 mysql 105 随着业务的发展 基于内存的NoSQL解决方案HOLD平台在高峰期一天支撑3000亿读