腾讯开始逐步上线互联网增值服务,业务量开始第一次爆炸。计费成为所有业务都需要的一个公共服务,不再是某个服务的专属。业务量的爆炸给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.jiangsushengnjb5.cn) shardkey=a。然后,Proxy改写SQL,根据路由信息,在最后增加对应的partition clause,然后发到所有的后端Set,如图2所示。
图2 Proxy建表语句
这样,就完成了一次建表任务,用户看到的是一张逻辑表test_shard,但是在后端创建了4个实体表test_shard,后续用户通过网关进行带shardkey的增删改查时,Proxy便会根据shardkey的路由将SQL发往指定Set。
全局自增字段
在单实例MySQL中,用户可以通过auto_increment.guangzhoushidz9L.cn属性生成一个唯一的值,在分布式数据库下,利用MySQL的自增属性,只能保证在一个后端实例内实现自增和全局唯一,无法保证整个集群的唯一。
为了保证整个集群的唯一性,很显然不能依赖于后端的数据库,而需要Proxy生成对应的值。同时在实际运行中,Proxy可能有多个,并且可能有重启等操作,通过Proxy自身也很难做到全局唯一,因此选用了ZooKeeper作为唯一值的生成工具。
通过ZooKeeper的分布式特性,可以保证即使多个Proxy同时访问,每次只会有一个Proxy能够成功拿到,使得生成的值是全局唯一。从性能上考虑,不可能每次都与ZooKeeper进行交互获取,因此每个Proxy每次都会申请一段值,都用完后才会向ZooKeeper进行申请。
图3 全局唯一字段表创建过程
这种设计方式实现了分布式环境下的自增属性全局唯一。每个Proxy缓存一定数量的值,并且增加单独线程负责向ZooKeeper申请值,使得性能影响降到最低,同时具有容灾特性,即使Proxy挂了或者重启,都能保证全局唯一。但是缺点是:多个Proxy一起使用的时候,只能保证全局唯一,不能保证单调递增。
全局唯一字段的创建方式和普通的自增字段一样:
create table auto_inc(a int auto_increment.henanshenggyq6.cn int) shardkey=b;
使用方式也相同:
insert into shard.hainansheng3j77.cn _inc ( a,b,d,c) values.sichuansheng5nv5.cn(1,2,3,0),(1,2,3,0);
对应的字段如果赋值为0或者NULL时,由Proxy生成唯一的值,然后修改对应的SQL发送到后端。同时也支持select last_insert.jiangxisheng1nfb.cn_id(),返回上次插入的值,每个线程互相独立。
分布式JOIN
在分布式数据库中,数据根据shardkey.shanxishengv33z.cn拆分到后端多个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.yunnansheng4sqm.cn * from t1 join g1。
分布式事务
针对分布式事务,TDSQL采用两阶段提交算法来实现分布式事务,其中Proxy作为协调者,状态数据持久化到全局事务管理系统中,目前选用的是TDSQL本身的一个InnoDB表来保存(gtid.guizhoushengn1r9.cn_log);所有的Group作为参与者来负责具体子事务的执行。
图5 分布式事务
Client向Proxy发送事务
Begin;
Statment1;
Statment2;
…
Proxy为该事务分配一个ID,并将SQL转为:
Xa begin “id”
Statment1;
Statment2;
…
Client提交事务
Client最终向Proxy发送commit。
Proxy对事务prepare
Proxy向所有参与该事务的Set发送:
- Xa end “id” 标识该事务的结束;
- Xa prepare “id” mysql将事务计入Binlog,并通过Binlog传递给Slave,不同于普通事务,写入Binlog之后该事务仍然没有提交;
- 如果任意Set在 prepare过程中失败或者超时,由于此时还没有写存储引擎日志,MySQL自动rollback这个事务,并向Client返回相应错误信息。
Proxy对事务commit
当Proxy收到所有Set的prepare响应之后,Proxy更新gtid_log表将对应XID的事务置为commit状态;Proxy.nanchangshij7p1.cn随后向所有Set发送Xa commit “id”,Set收到该请求之后提交该事务。
Proxy返回Client OK
Proxy等待所有Set的commit.fujianshengtn5j.cn响应,当所有Set返回成功,Proxy返回前台成功。若其中一台返回失败(当Set发生重启等故障时,需要等待Agent补提交该事务,因而当前属于未提交状态),Proxy返回前台状态未知,稍后请继续查询事务状态。
当Proxy在第四步写完commit后,开始逐个Set提交事务,当还没有完成所有Set提交时Proxy发生宕机,剩余Set中未提交的事务由Agent来提交,以此来保证事务的一致性。Agent会定期通过命令Xa recover查询MySQL中处于prepare状态的事务,再对照gtid-log表查询该事务是否处于commit.tangshanshi9p7n.cn状态,如果是则comimt。否则可能由于prepare成功后写gtid_log失败,因而Agent需要将该事务abort。
多种模式的读写分离
TDSQL支持三种模式的读写分离。第一种模式下网关开启语法解析的配置,通过语法解析过滤出用户的select读请求,默认把读请求直接发给备机。这种方案的缺点有两个:1. 网关需要对SQL进行分析,降低整体性能;2. 当主备延迟较大时,直接从备机获取数据可能会得到错误的数据。
除了上述模式,TDSQL支持通过增加Slave注释标记,将指定的SQL发往备机。即在SQL中添加/slave.qinghaisheng8oqe.cn/这样的标记,该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.changchunshin3zx.cn-MySQL 5.7.x两个分支版本,后续我们会紧密跟进社区并及时应用官方补丁,同时不断针对金融场景的特性对数据库内核进行优化,以此来提升数据库性能和稳定性。当前分布式事务处于初级阶段,对ZooKeeper.zhengzhoushirlp3.cn的依赖性较强,后续可能针对分布式事务的可靠性做持续改进。
“云先行,智未来”。当前,企业”上云”节奏正在加速,云计算已经与工业、交通、金融、教育、生活服务等领域深度结合,特别在以人工智能技术为代表的新一波技术浪潮的推动下,企业一方面通过云技术增强了自身的数据连接能力与智能应用能力,提升业务创新的深度和高度;另一方面,基于云计算之上的大数据、人工智能等新技术的发展与应用,让企业可以以较小的成本、更高效地挖掘出快速提升企业业务的数据与方法,实现云、数、智的自然融合和协力发展。当然,发展的过程中不可避免会出现新问题、新挑战、新趋势,如何化挑战为机遇,以“云先行,智未来”为主题的CCTC 2017将直面问题挑战,探索前行的方向。
峰会总览
两天的日程,满满当当。今年的大会持续2天,大会第一天采用免费申请的形式,目前名额还有少量,请抓紧最后机会。第二天的四大技术峰会,采用售票形式,票价不高,完全是抵消主办方的部分会务成本,相信理性的开发者应该愿意为技术买单,点击购票。
整体来看,本次大会议题精彩纷呈,主办方从整个云计算、大数据的全局出发综合考虑、统筹兼顾,努力为参会者呈现一幅云计算、大数据蓬勃发展的全景图。具体到议程上来,两天8场专题会场,无论从专题的选定、讲师的邀请,还是议题的策划,主办方力图为大家从各个维度展示云技术的前沿研究、技术发展、产业应用等最新状态。
技术层面,在秉承“最纯粹的技术干货分享,最接地气的深度行业案例实践”宗旨下每年的CCTC 都邀请云技术领域极具影响力的讲师登台分享,今年,我们邀请到Mesosphere联合创始人兼CTO Tobias Gunter Knaup、Rancher Labs联合创始人兼CEO梁胜,分别带来Mesos和Rancher领域的最新技术进展。
在勒索病毒WannaCry肆虐全球的大背景下,来自UCloud 块存储研发总监彭晶鑫给我们聊聊如何重新定义云数据保护显得尤为及时;另外,人工智能大潮下,软件架构的演进之路会是怎样,来自普元CTO焦烈焱将一一为我们分解;微服务领域,来自58集团技术委员会主席孙玄为我们剖析实施微服务的关键技术,第四范式算法研发工程师涂威威将详细介绍大规模分布式机器学习系统设计的技术经验等等。
应用层面,京东集团运营研发部高级总监李鹏涛将带来京东在大数据领域的应用和价值挖掘,PPmoney大数据算法总监黄文坚则带来TensorFlow在金融领域的应用,另外,还有来自西部数据、中国移动、恒丰银行、国家气象局、MoPaaS等技术专家带来云技术在各自企业的应用实践,非常值得聆听。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/7410.html