支持自动水平拆分的高性能分布式数据库TDSQL

随着互联网应用的广泛普及,海量数据的存储和访问成为系统设计的瓶颈问题。对于大型的互联网应用,每天几十亿的PV无疑对数据库造成了相当高的负载。给系统的稳定性和扩展性造成了极大的问题。通过数据的切分来提高系统整体性能,扩充系统整体容量,横向扩展数据层已经成为架构研发人员首选的方式。

2004年,腾讯开始逐步上线互联网增值服务,业务量开始第一次爆炸。计费成为所有业务都需要的一个公共服务,不再是某个服务的专属。业务量的爆炸给DB层带来了巨大的压力,原来的单机模式已经无法支撑。伴随计费公共平台的整合建设,在DB层开始引入分库分表机制:针对大的表,按照某个key预先拆成n个子表,分布在不同的机器节点上。逻辑层在访问DB时,自己根据分表逻辑将请求分发到不同的节点。在扩容时,需要手工完成子表数据的搬迁和访问路由的修改。DB层在业务狂潮之下,增加各种工具和补丁来解决容量水平扩展的问题。2012年TDSQL项目立项,目标为金融联机交易数据库。

TDSQL(Tencent Distributed MySQL,腾讯分布式MySQL)是针对金融联机交易场景推出的高一致性、分布式数据库解决方案。产品形态为一个数据库集群,底层基于MySQL,对外的功能表现上与MySQL兼容。截至2017年,TDSQL已在公司内部关键数据领域获得广泛应用,其中之一作为Midas(米大师)核心数据库,经受了互联网交易场景的考验。Midas作为腾讯官方唯一数字业务支付平台,为公司移动App(iOS、Android、Win phone等)、PC客户端、Web等不同场景提供一站式计费解决方案。

TDSQL规定shardkey为表拆分的依据,即进行SQL查询时,shardkey作为查询字段指明该SQL发往哪个Set(数据分片)。在分库分表之前需要Schedule初始化集群,我们这里称作一个Group。在初始化Group时要确定最初的分片大小,因而需要确定准备几套Set。例如,我们需要对逻辑表拆分成四张子表,需要我们在初始化集群时准备四个Set,同时指定每个Set的路由信息,并将这些路由信息写入ZK,如图1所示。

图1 TDSQL分库分表

完成集群初始化后,Proxy监控ZooKeeper中的路由节点,当发现新的路由信息后,更新新的路由到本地。当用户通过Proxy创建表时,一个建表语句发给Proxy必须指定shardkey,例如create table test_shard(a int, b int) shardkey=a。然后,Proxy改写SQL,根据路由信息,在最后增加对应的partition clause,然后发到所有的后端Set,如图2所示。

图2 Proxy建表语句

这样,就完成了一次建表任务,用户看到的是一张逻辑表test_shard,但是在后端创建了4个实体表test_shard,后续用户通过网关进行带shardkey的增删改查时,Proxy便会根据shardkey的路由将SQL发往指定Set。

在单实例MySQL中,用户可以通过auto_increment属性生成一个唯一的值,在分布式数据库下,利用MySQL的自增属性,只能保证在一个后端实例内实现自增和全局唯一,无法保证整个集群的唯一。

为了保证整个集群的唯一性,很显然不能依赖于后端的数据库,而需要Proxy生成对应的值。同时在实际运行中,Proxy可能有多个,并且可能有重启等操作,通过Proxy自身也很难做到全局唯一,因此选用了ZooKeeper作为唯一值的生成工具。

通过ZooKeeper的分布式特性,可以保证即使多个Proxy同时访问,每次只会有一个Proxy能够成功拿到,使得生成的值是全局唯一。从性能上考虑,不可能每次都与ZooKeeper进行交互获取,因此每个Proxy每次都会申请一段值,都用完后才会向ZooKeeper进行申请。

图3 全局唯一字段表创建过程

这种设计方式实现了分布式环境下的自增属性全局唯一。每个Proxy缓存一定数量的值,并且增加单独线程负责向ZooKeeper申请值,使得性能影响降到最低,同时具有容灾特性,即使Proxy挂了或者重启,都能保证全局唯一。但是缺点是:多个Proxy一起使用的时候,只能保证全局唯一,不能保证单调递增。

全局唯一字段的创建方式和普通的自增字段一样:

create table auto_inc(a int auto_increment,b int) shardkey=b;

使用方式也相同:

insert into shard.auto_inc ( a,b,d,c) values(1,2,3,0),(1,2,3,0);

对应的字段如果赋值为0或者NULL时,由Proxy生成唯一的值,然后修改对应的SQL发送到后端。同时也支持select last_insert_id(),返回上次插入的值,每个线程互相独立。

在分布式数据库中,数据根据shardkey拆分到后端多个Set中,每个后端Set保存的都只是一部分数据。我们可以方便地在一个Set内做各种复杂的操作,如JOIN、子查询等。分布式JOIN依赖于网关的语法分析,何为语法分析?简单来说,语法分析主要做两方面的事:判断输入是否满足指定的语法规则,同时生成抽象语法树。对于词法分析以及语法分析,开源有多种现成的工具,不需要从头开始做,Linux下用的比较多的是Flex和Bison。

图4 语法分析过程

有了语法分析的支持,对于涉及分布式JOIN的查询,例如表t1和t2要做JOIN操作,可能使用不同的字段作为shardkey,这样根据shardkey路由后,相关记录可能分布在两个Set,网关分析后先将数据表t1数据取出,然后再根据t1的shardkey去获取t2的数据,网关在这个过程中先做语法解析再进行数据聚合,最后返回给用户结果集。此外,在实际业务中,有一些特殊的配置表,这些表都比较小,并且变动不多,但是会和很多其他表有关联,对于这类表没必要进行分片,因此支持一种叫做全局表的特殊表。如果用户创建时指定是全局表的话(g1),该表全量存放在后端的所有Set中,查询时随机选择一个Set,修改时修改所有Set。如果对全局表进行JOIN的话,就不需要限制条件,即支持select * from t1 join g1。

针对分布式事务,TDSQL采用两阶段提交算法来实现分布式事务,其中Proxy作为协调者,状态数据持久化到全局事务管理系统中,目前选用的是TDSQL本身的一个InnoDB表来保存(gtid_log);所有的Group作为参与者来负责具体子事务的执行。

图5 分布式事务

Begin;

Statment1;

Statment2;

Proxy为该事务分配一个ID,并将SQL转为:

Xa begin “id”

Statment1;

Statment2;

Client最终向Proxy发送commit。

Proxy向所有参与该事务的Set发送:

Xa end “id” 标识该事务的结束;

Xa prepare “id” mysql将事务计入Binlog,并通过Binlog传递给Slave,不同于普通事务,写入Binlog之后该事务仍然没有提交;

如果任意Set在 prepare过程中失败或者超时,由于此时还没有写存储引擎日志,MySQL自动rollback这个事务,并向Client返回相应错误信息。

当Proxy收到所有Set的prepare响应之后,Proxy更新gtid_log表将对应XID的事务置为commit状态;Proxy随后向所有Set发送Xa commit “id”,Set收到该请求之后提交该事务。

Proxy等待所有Set的commit响应,当所有Set返回成功,Proxy返回前台成功。若其中一台返回失败(当Set发生重启等故障时,需要等待Agent补提交该事务,因而当前属于未提交状态),Proxy返回前台状态未知,稍后请继续查询事务状态。

当Proxy在第四步写完commit后,开始逐个Set提交事务,当还没有完成所有Set提交时Proxy发生宕机,剩余Set中未提交的事务由Agent来提交,以此来保证事务的一致性。Agent会定期通过命令Xa recover查询MySQL中处于prepare状态的事务,再对照gtid-log表查询该事务是否处于commit状态,如果是则comimt。否则可能由于prepare成功后写gtid_log失败,因而Agent需要将该事务abort。

TDSQL支持三种模式的读写分离。第一种模式下网关开启语法解析的配置,通过语法解析过滤出用户的select读请求,默认把读请求直接发给备机。这种方案的缺点有两个:1. 网关需要对SQL进行分析,降低整体性能;2. 当主备延迟较大时,直接从备机获取数据可能会得到错误的数据。

除了上述模式,TDSQL支持通过增加Slave注释标记,将指定的SQL发往备机。即在SQL中添加/slave/这样的标记,该SQL会发送给备机,即用户能够根据业务场景可控地选择读写分离,即使主备延迟比较大,用户也能够根据需要灵活选择从主机还是备机读取数据,这种模式下网关不需要进行词法解析,因而相比第一种方案提高了整体性能。但是,这种方案的缺陷是改写了正常SQL,需要调整已有用户代码,成本较高,用户可能不太愿意接受。

表1 三种读写分离模式比较

针对前两种读写分离的不足,最新版本的TDSQL增加了基于只读帐号的读写分离模式。这种模式下,由只读帐号发送的请求会根据配置的属性发给备机。有两种可配属性,IDC属性和备机延迟属性。IDC属性可配置三种属性:1. 为同IDC属性,即只读帐号的请求必须发往同IDC的备机;2. 优先发给同IDC的备机,但当同IDC的备机不存在或宕机时,发往不同IDC的备机;3. 如果找不到满足条件的备机,则发往主机。延迟属性:如果延迟超过阀值,认为该备机不可用。只读帐号能够在既不改变原有用户代码,又不影响系统整体性能的前提下,同时提供多种可配参数解决读写分离的问题,更具有灵活性和实用性。

2014年微众银行设立之初,在其分布式的去IOE架构中,TDSQL承担了去O的角色,以TDSQL作为交易的核心DB,承载全行所有OLTP业务。2015年,TDSQL和腾讯云携手,正式启动“TDSQL上云”的工作,接入了一系列传统以及新型金融企业,覆盖保险、证券、理财、咨询等金融行业。目前,分布式TDSQL正作为腾讯日益重要的金融级数据库,搭建着上百个实例,部署于上千台机器,日均产生TB级数据,承载着公司内外各种关键业务。

在未来,TDSQL重点会在数据库性能、分布式事务、语法兼容三个方面做改进。目前TDSQL基于MariaDB 10.1.x、Percona-MySQL 5.7.x两个分支版本,后续我们会紧密跟进社区并及时应用官方补丁,同时不断针对金融场景的特性对数据库内核进行优化,以此来提升数据库性能和稳定性。当前分布式事务处于初级阶段,对ZooKeeper的依赖性较强,后续可能针对分布式事务的可靠性做持续改进。由于TDSQL在分表环节对语法层做了一些限制,将来我们希望通过对网关解析器的改进,使其能够支持更丰富的语法、词法。

转载于:https://www.cnblogs.com/jellyru/p/6894778.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/400912.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一些有趣的B+树优化实验

🚀 优质资源分享 🚀 学习路线指引(点击解锁)知识定位人群定位🧡 Python实战微信订餐小程序 🧡进阶级本课程是python flask微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一…

Tarjan的强联通分量

求强联通分量有很多种。 《C信息学奥赛一本通》 中讲过一个dfs求强联通分量的算法Kosdaraju,为了骗字数我就待会简单的说说。然而我们这篇文章的主体是Tarjan,所以我肯定说完之后再赞扬一下Tarjan大法好是不是 首先我们讲一下强联通分量 强联通分量指的…

XXE漏洞

简介 XXE (XML External Entity Injection) 漏洞发生在应用程序解析 XML 输入时,没有禁止外部实体的加载。 简单的理解,一个实体就是一个变量,可以在文档中的其他位置引用该变量。 实体主要分为四种: 内置实体 (Built-in entities…

Linq之Expression高级篇(常用表达式类型)

目录 写在前面 系列文章 变量表达式 常量表达式 条件表达式 赋值表达式 二元运算符表达式 一元运算符表达式 循环表达式 块表达式 总结 写在前面 首先回顾一下上篇文章的内容,上篇文章介绍了表达式树的解析和编译。如果忘记了,可以通过下面系列文章提供的…

NetCore框架WTM的分表分库实现

🚀 优质资源分享 🚀 学习路线指引(点击解锁)知识定位人群定位🧡 Python实战微信订餐小程序 🧡进阶级本课程是python flask微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一…

WordPress WP Photo Album Plus插件‘wppa-tag’跨站脚本漏洞

漏洞名称:WordPress WP Photo Album Plus插件‘wppa-tag’跨站脚本漏洞CNNVD编号:CNNVD-201301-458发布时间:2013-01-24更新时间:2013-01-24危害等级: 漏洞类型:跨站脚本威胁类型:远程CVE编号&…

SpringCloudAlibaba分布式流量控制组件Sentinel实战与源码分析(上)

🚀 优质资源分享 🚀 学习路线指引(点击解锁)知识定位人群定位🧡 Python实战微信订餐小程序 🧡进阶级本课程是python flask微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一…

【单元测试框架unittest】

转载于:https://www.cnblogs.com/ppppying/p/6899750.html

C++ 炼气期之基本结构语法中的底层逻辑

🚀 优质资源分享 🚀 学习路线指引(点击解锁)知识定位人群定位🧡 Python实战微信订餐小程序 🧡进阶级本课程是python flask微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一…

优惠券的工厂与策略模式实现方案

🚀 优质资源分享 🚀 学习路线指引(点击解锁)知识定位人群定位🧡 Python实战微信订餐小程序 🧡进阶级本课程是python flask微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一…

WP8.1学习系列(第九章)——透视Pivot开发指南

Windows Phone 8 的 Pivot 控件 2014/6/18 适用于:Windows Phone 8 和 Windows Phone Silverlight 8.1 | Windows Phone OS 7.1 Windows Phone Pivot 应用提供了一种快速管理视图或页面的方法。该方法可以用于筛选大型数据集、查看多个数据集或切换应用视图。例如&a…

ESP8266 系统环境搭建

🚀 优质资源分享 🚀 学习路线指引(点击解锁)知识定位人群定位🧡 Python实战微信订餐小程序 🧡进阶级本课程是python flask微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一…

无线网络配置

转载于:https://www.cnblogs.com/lingxzg/archive/2013/02/09/2909606.html

Java编程之反射中的注解详解

“注解”这个词,可谓是在Java编程中出镜率比较高,而且也是一个老生常谈的话题。我们之前在聊Spring相关的东西时,注解是无处不在,之前我们简单的聊过一些“注解”的相关内容,比如在Spring中是如何进行“注解”组合的。…

SCCM 2012 R2实战系列之十三:辅助站点部署

由于最近几个月一直处于AD升级项目中,很久没有更新SCCM的技术文档了。SCCM 2012中的辅助站点部署方法还是比较特别的,需要注意的地方也非常多,今天跟大家分享辅助站点的具体部署和配置方法。1. 前提条件加入域环境 安装IIS组件安装BITS和远程…

DevOps落地实践点滴和踩坑记录-(1)

🚀 优质资源分享 🚀 学习路线指引(点击解锁)知识定位人群定位🧡 Python实战微信订餐小程序 🧡进阶级本课程是python flask微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一…

2014年度优秀员工代表发言稿

2019独角兽企业重金招聘Python工程师标准>>> 尊敬的各位领导和亲爱的同事们,大家好! 作为优秀员工代表在这里发言,我很感谢刘总、周总、李总、漆总以及公司各层领导的信任和支持!我感到十分荣幸,同时也感到…

无需另配定时器在STM32 HAL下实现微秒级延时(兼容FreeRTOS)

目录前言一、代码部分二、使用和验证1.引入头文件2.初始化3.使用和验证三、可移植性总结前言 接触HAL库差不多两年了,一直苦于HAL库没有自带微秒级的延时,网上的前辈们给出的解决方案要么是改写HAL_Delay的延时时间,要么就是额外占用一个定时…

×××S 2012 交互式报表 -- 同步交互式排序

S 2012 交互式报表 -- 同步交互式排序步骤1:首先,在刚才的“交互式排序”示例报表中再拖拉一个“Chart”,设置为长条图,从报表数据窗口中将销售金额、销售数量拖至“Values”,将产品大类拖放至“Category Groups”区域…

SpringCloud GateWay 万字详解

🚀 优质资源分享 🚀 学习路线指引(点击解锁)知识定位人群定位🧡 Python实战微信订餐小程序 🧡进阶级本课程是python flask微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一…