TDSQL简介

发布时间:2018-06-30 13:59:43   来源:文档文库   
字号:

TDSQL(Titan Distribute SQL) — 一种分布式数据库之容灾篇

一、传统的分库分表及由此引入的问题

由于业务数据量巨大以至于无法单表存储,于是,我们习惯了分库分表的方式。最常用的莫过于按照QQ号的后三位分1000表,除此之外,还有按照大区分表,按照时间分表,等等。于是我们习惯了下面这样一种SVR与DB交互的架构结构。

图1—传统的分库分表存储

这个我们习以为常的数据库存储结构,其实包含了一些问题,本篇将主要讨论主备一致性切换问题,并给出TDSQL主备切换的方式。问题如下:

1、  主备的异步同步,在主机宕机的情况下,无法保证数据已经同步到了备机。

2、  人工切换,则对DBA同学的实时处理提出非常高的要求。

3、  自动切换,可能出现不同SVR对于主DB的健康状态判断不一致,造成不同SVR把数据写入到不同DB的情况即——脑裂。

4、  即使通过仲裁节点来统一调度SVR连向主DB或者备DB,如果流程处理的不好,也可能因为SVR感知切换的时间差在短时间内造成脑裂。

如何解决上面的问题,业界给出了很多的方案,例如国外有Galera这种通过协议插件来实现一致性的方案(但这种方案在跨IDC时的性能非常差),国内也有阿里RDS,TDDL,360的atlas中间件,但上述的方案要么在主备切换的一致性,要么在主动切换,要么在性能上都会有或多或少的问题,因此我们在参考上述方案的基础上实现了今天要给大家介绍的方案Titan Distribute SQL — TDSQL。

二、TDSQL主备切换方案

2.1 TDSQL容灾架构

图二、TDSQL容灾架构

图二是一个大家熟悉的具备调度能力的分布式集群,下面分别来介绍一个各个模块的作用及如何互动。

DB——图中的绿色部分,是集群的核心部分,也就是mysql节点。为了实现主备的强一致性和较高的性能,这里必须使用我们在Mariadb 基础上进行二次开发的MySQL。注意,只有主DB提供写服务,其它DB会被Agent自动设置成只读。

Agent ——监控模块,Agent监控MySQL节点的健康状况,并上报心跳给Scheduler。

Node ——每个MySQL进程和Agent要一起部署,二者组合在一起得到一个最小的存储控制单元Node。

SET——为了实现容灾,通常使用一主N备个节点来组成一个最小的容灾存储单元,主Node和备Node存储的数据一致,通过后面介绍的强同步来同步数据。为了实现跨IDC容灾,不同的Node节点需要部署在不同的IDC。

Scheduler ——调度模块,Scheduler接收Agent的请求,并判断该DB是否宕机,如果宕机时间超过阀值,则会触发容灾流程。

Proxy——业务请求分发模块,其实是一个MySQL代理,适配MySQL协议,并把请求发送到后端的。

Zookeeper ——一个开源的一致性存储集群,在TDSQL架构中,所有控制节点通过Zookeeper进行交互。

2.2 TDSQL各个控制模块的容灾

1、Agent —Agent挂掉存在两种情况:

1、整个物理机器出现类似掉电的情况,在这种情况下是要做Node节点的主备切换的,这个时候Agent在Zookeeper创建的心跳节点(一个zookeeper的临时节点)将会消失,Scheduler监控到心跳节点消失,在超过阀值时间后,将会出发一个容灾流程。

2、Agent本身挂掉,Agent启动的时候会有一个监控进程监控工作进程是否活着,如果发现Agent进程非正常退出,会主动把Agent拉起,而从Agent挂掉到拉起的时间足够短,因此不会造成Scheduler触发主备切换流程。

2、Scheduler——多个Scheduler通过Zookeeper进行选举,保证任何时刻都有且只有一个Scheduler在提供服务。

3、Proxy ——可以使用多种方式容灾,例如使用LVS、使用MYSQL自带的DNS,或者给业务端一个ip列表让其自动轮询。

2.3 主备数据复制

2.3.1 传统的异步复制:

传统的MySQL异步复制,是把主机(这里的主机是指主MySQL进程,本节其它地方的主机与此解释相同)Binlog中的事务异步的发给备机。主机并不等备机的应答。这就存在一个主备延迟的问题。通常我们可以通过在备机执行Show Slave Status来查看主备的延迟。在主备延迟比较大的情况下,直接进行主备切换会造成大量的脏数据。

2.3.2 半同步复制

MySQL5.5引入了半同步复制。所谓的半同步复制,是指主机不仅要把同步事务发给备机,而且要等待备机的应答。由于备机只是把同步事务写入Relay Log就返回主机应答,而不需等要把Relay Log中的事务加载到引擎中后再返回,因此备机的返回给主机的应答会很快。而主机必须等待备机的应答之后,才返回给用户应答(如果有多台备机,只要有一个备机给与应答就可以返回前端用户了)。这就保证了主备的一致。

图三—MySQL半同步复制流程[1]

上述流程保证了主备数据的一致(对于备机返回应答,主机没有来得及返回前端响应就宕机的情况下,参考下面的注释),但如果备机一直不给主机(例如网络丢包)应答,则主机的事务处理会被卡住,MySQL利用rpl_semi_sync_master_timeout来设置了这个超时时间,当应答时间超过此阀值时,主备同步会自动变成异步复制。

注:

数据库操作中有一个原则:

1、  如果返回给客户端的是成功的应答,则证明此事务已经落盘。

2、  如果返回的是失败的应答,则证明操作对数据库不会有任何影响。

3、  如果没有返回前端应答,则操作可能成功也可能失败。在实际应用中,这种情况需要的是二次核对。

2.3.3 强同步复制

2.3.2中主机长时间收不到备机应答的情况下会变成异步复制的机制,对于普通的应用是没有关系的,但是对于一致性要求很高的情况下,这种机制是不能被允许的。同时,在原来的机制上,主备同步需要处理线程做同步等待,也就是说如果有1w笔并发,就需要1w个处理线程在等待,这造成了性能的严重下降。

因此,我们在半同步复制的基础上做了修改,关闭了半同步向异步同步切换的过程,同时把主备同步事务时的同步等待机制改成异步处理,这样就可以使用一个异步线程池来完成高并发。

为了不影响和业务请求和宕机情况,在强同步复制的SET中,最小配置是一主两备。

2.3.4 全局事物标示符号(Global Transactions Identifier——GTID)

GTID代表一个数据库事务, MySQL 5.6 版本增加了GTID2来强化数据库的主备一致性,故障恢复以及容错能力。

GTID的官方定义是:GTID = source_id:transaction_id,source_id 代表执行实物的主库uuid(server_uuid), transaction_id 是一个从1开始的自增计数,表示在这个主库上执行的第n个事务。MySQL会保证事务与GTID之间的1:1映射。

在TDSQL切换后重建主备关系,而同步点就是通过GTID给出的。

我们假设主机的Server_uuid 为M,GTID为M:123456,同理备机S1的GTID为M:123455,备机S2的GTID为M:123456,在切换的时候,由于S2的同步点是最新的,所以新建的同步关系是S1 为备机,S2为主机, S1只要把M:123455发给S2即可建立新的同步点,而发生在S2上的新事物,从S2:1开始数序向下写。

2.4 主备一致性切换流程

经过上面的几个章节,现在我们来描述主备一致性切换流程,参见图一:

1、  当Scheduler监控Master的Agent上报心跳为宕机状态,或者Master的Agent维护的zookeeper 心跳节点消失,并且这段时间超过阀值时,则出发一个切换流程,进入步骤2。

2、  Scheduler会判断备机是否满足切换要求,判断条件如下

a)         至少有两个备机节点是健康的。

b)         备机和主机节点的延迟在阀值以内。

c)         备机的GTID是有效的。

如果满足上述切换条件,选出可以参与本次选举主节点的备节点列表(后续简写为参选列表),则进入3,否则切换流程失败。

3、  Scheduler判断主节点宕机类型,如果是zookeeper中的心跳节点存在,但是心跳节点中的信息反映为主DB宕机,则下发降级主DB命令,进入4;如果是主节点Agent在zookeeper中维护的节点不存在(这种情况一般是主节点所在的物理机器出现问题,例如掉电)进入步骤5。

4、  主节点Agent接收到降级的信息后,会把主DB设置为只读模式,并安全杀死所有连接,并返回给Scheduler降级主DB完成。

5、  Scheduler向参选列表中的所有备机发送加载relay log的命令,进入6.

6、  参选列表节点Agent 加载relay log,完成后上报同步点GTID给Scheduler。

7、  Scheduler在收到所有参选列表节点的应答后,选出具有最大GTID的节点作为新的主节点。并下发新主节点给所有参选列表中的节点。

8、  参选列表节点Agent重建主备同步关系,设置同步主DB为Scheduler新选出来的主节点,被选为主节点的Agent会把DB设置成读写模式提供读写服务,然后应答Scheduler。

9、  Scheduler修改SET中的主备关系。

10、Proxy监控主备关系zookeeper节点,感知到了主备关系的变化,把后续的请求发送给新的主节点。

以上就完成了一次主备切换。

三、总结

强一致性的切换需要两个条件:

1、  主备数据的一致性保证,这个通过我们修改的强同步复制实现。

2、  主备切换流程的合理,这里的主要理论依据是,任何时候不能在一个SET中出现两个主节点。这个我们通过2.4中的流程进行了保证。

综上,我们基本实现了一个强一致性容灾的机制,当然这里也会有些问题,例如主备切换时没有应答的客户端请求其实是无法判断最终结果的,这个需要在业务侧对账或者在更上层来完善这个主备切换的机制,这些问题我们会继续关注并解决。

本文来源:https://www.2haoxitong.net/k/doc/a7e0bad13b3567ec112d8a32.html

《TDSQL简介.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

文档为doc格式