分布式MySQL数据库TDSQL架构分析

腾讯计费平台部托管着公司90%以上的虚拟账户,如QB、Q点、包月服务、游戏的二级账户等,为了保证能顺畅支撑公司各大业务的实时在线交易,并且在各种灾难场景下数据是一致并且可用的,对系统的可用性、一致性切换要求非常高,因此计费团队历来都非常重视高一致性存储系统的建设。

到目前为止,计费高一致性存储层的解决方案大致经过了3个阶段,本文将分享最新的基于MySQL的分布式解决方案。

随着业务的发展,基于内存的NoSQL解决方案HOLD平台在高峰期一天支撑亿读写,证明了分布式Cache的巨大价值;但随着各种业务的接入,NoSQL方案的不足也逐步显现出来了,如下所示。

适用的业务场景比较有限,仅提供get/set操作,有不少业务场景希望能通过记录中的其他字段做索引来查询,比如流水类业务。

不是所有的数据都是热点,一台64GB内存机器提供的有效内存空间大概在50GB左右,而采用Fusion卡的机型容量一般在1TB以上,对比起来,如果所有数据放入分布式Cache明显是一种极大的浪费,最合理的当然是热点在HOLD,冷数据采用基于磁盘的存储。

计费平台部多年来在支付领域有了相当多的技术积累,HOLD作为NoSQL系统功能有限,因此建造一套更加强大通用的高一致性存储系统将整个支付领域的实时数据(重点是账户数据、用户订单数据,以及海量的流水数据)统一管理起来非常有价值。

基于上面的分析,结合我们在MySQL领域多年的应用和优化经验,最终决定在MySQL存储引擎基础之上,打造一套分布式的SQL系统。

保持原来的MySQL协议,这样以前访问MySQL系统的C++、Java各类系统都不需要修改,DBA能继续保持原来大部分使用习惯。

自动的跨IDC容灾切换,同时保证数据一致性,对于提交成功的事务保证一笔不丢,达到银行级对容灾的要求。

灵活的容量伸缩机制,对业务透明,解决MySQL本身扩容不灵活的问题。

重点支持OLTP类型的在线业务。

整体架构

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

图1TDSQL架构

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

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

管理set,提供创建、删除set、set内节点替换等工作;

所有的DDL操作统一下发和调度;

监控set内各个节点的存活状态,当set内主节点故障,发起高一致性主备切换流程;

监控各个set的CPU、磁盘容量、各个表的资源消耗情况,必要的时候自动发起扩容流程;

Scheduler自身的容灾通过ZooKeqzer的选举机制完成,保证中心控制节点无单点。

Agent模块负责监控本机MySQL实例的运行情况,主要功能包括:

用短连接的方式周期性访问本机的MySQL实例,检测是否可读、可写,若发生异常,会将异常信息上报到ZooKeeper,最终会由上面描述的Scheduler模块检测到这个异常情况,从而发起容灾切换;

检测主备复制的执行情况,会定期上报主备复制的延时和延迟的事务数,若发生了主备切换,自动向新主机重建主备,因此MySQL的主备不需要DBA干预,对于新增的实例会自动采用xtrabackup通过主机自动重建数据;

检测MySQL实例的CPU利用率和各个表的请求量、数据量、CPU利用率,上报到ZooKeeper,ZooKeeper通过全局的资源情况抉择如何扩容、缩容;

监控是否有下发到自身的扩容任务,如有则会执行扩容流程(下面会有描述);

监控是否要发生容灾切换,并按计划执行主备切换流程。

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

解析SQL,将识别出的DDL语句直接存到ZooKeeper,让Keeper来统一调度;

WatchZooKeeper的路由信息,拉取最新的路由表保存到本地文件和内存;

将SQL请求路由到对应的set,支持读写分离;

对接入的IP、用户名、密码进行鉴权;

记录完整的SQL执行信息,与秒级监控平台对接完成实时的SQL请求的时耗,成功率等指标监控分析;

对count、distinct、sum、avg、max、min、orderby、groupby等聚合类SQL一般需要访问后端的多个set,网关会分析结果并做合并再返回,暂不支持跨setjoin和分布式事务;

网关无状态,既支持与业务部署到一起,也可以独立部署(可通过TGW或者LVS做容灾)。

自动扩容机制

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

垂直扩容。一般通过升级硬件来实现,比如更换更好的CPU,将传统的sas盘换成FusionIO卡这类,然后针对新硬件调整好参数,在硬件结构变化比较大的时候,性能甚至能达到上十倍的提升。但垂直扩容有比较大的局限,就是这种模式随着业务的突增还是比较容易达到瓶颈,特别是面对互联网海量用户的时候,所以在互联网应用场景下,一般仅将垂直扩容当做一个辅助的手段。

水平扩容。常用的有2种方法,一是不同的库或者表部署到不同的实例,二是一张表需要根据某个字段拆分到不同的字表中(数据分片),这种策略在互联网系统中非常常见,很多系统会将这2种水平扩容的方法结合起来使用;

通过上述2种扩容方法的比较,为了应对海量扩展的需求,应该是重点选用水平扩容的方法。但水平扩容的实现一般对业务是有感知的,比如采用什么规则来拆表,拆开的表放到哪些节点,如果某个子表还有瓶颈应该怎么扩容,扩容是否还需要业务配合等等这些事情如果全部交给业务会比较繁琐,因此这些需求应该尽量全部交给TDSQL自身来完成,对业务完全透明。

分表逻辑

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

图2TDSQL的逻辑表

每个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(-)。

图3策略2的扩容流程

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

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

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

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

容灾机制

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

在MySQL发展的早期,就提供了异步复制的技术,只要写的压力不是特别大,在网络条件较好的情况下,发生主备切换基本上能将影响控制到秒级别,因此吸引了很多开发者的







































北京中医白癜风医院哪家最好
北京哪家医院治白癜风费用少



转载请注明:http://www.xcqg58.com/lsqy/6988.html

  • 上一篇文章:
  •   
  • 下一篇文章: 没有了