APP下载

分布式数据库在湖南电信IT架构转型中的探索和应用

2019-01-06熊游泳

电脑知识与技术 2019年32期

熊游泳

摘要:随着4G网络和移动互联网业务的迅猛发展,面对海量数据处理、高并发交易的压力,传统的集中式数据库如Oracle基本不支持大规模自动扩展,逐渐表现出其局限性。中国电信基于开源的Mysql数据库和Mycat分布式数据库中间件,结合企业实际,自主研发的分布式数据库系统在湖南电信IT系统中得到广泛应用,解决了海量交易型业务数据的存储和高效访问的难题,实现了低成本、高性能、高可用、高扩展,有利的支撑了企业IT架构互联网化转型。

关键词:MySQL;Mycat;分布式数据库

中图分类号:TP391 文献标识码:A

文章编号:1009-3044(2019)32-0018-05

1概述

湖南电信自1995年“九七工程”建设第一个IT系统开始,截止到2017年底,已建成的IT系统达到288套。其中近95%的系统使用的是Oracle RAC数据库。进入互联网时代以来,特别是近几年,随着4G网络和移动互联网业务的迅猛发展,电信核心系统数据量均出现了大规模的增长,以计费系统为例,每月的清单数据量从2014年的5TB增长到2019年的30TB,5年时间数据量增长近6倍,由于原有系统Oracle RAC的shared ev-erything的架构,10的处理能力及扩展能力有限,并且随着节点数的增加,数据库系统的稳定性和高性能难以保障。因此,海量数据的存储、处理与访问成为当时湖南电信乃至整个中国电信IT系统设计与使用中亟待解决的问题。

中国电信自2017年开始,对标业界领先公司,采用主流互联网公司技术路线,基于开源的Mysql数据库和Mycat分布式数据库中间件,结合企业实际,自主研发了高性能、高可用、高扩展的分布式数据库,在低成本、可扩展、快速响应等方面拥有巨大优势,成为湖南电信企业级rr架构的发展方向。

2分布式数据库概念的提出

Oracle、Mysql等传统的关系数据库非常成熟并且已大规模商用,为什么还要用分布式数据库呢?主要是由于中国互联网业务的迅猛发展,所生成的海量数据对存储、处理、访问的性能要求越来越高,传统数据库存在着先天性的缺陷,即单机性能有限,扩展困难,且随着节点数的增加,数据库系统的稳定性和高性能难以保障,已经无法满足海量数据存储及高性能访问的要求。因此,业界提出了分布式数据库的概念。简单来说,分布式数据库是采用分库分表等数据切分的方式提供可扩展的数据存储,并且采用数据库代理方式为应用提供透明访问及平滑扩缩容能力,包括数据的存储与数据的访问两部分的内容。

3分布式数据库的数据切分

分布式数据库的数据存储通过数据切分的方式,按照特定的规则,将一个数据库中的数据分散存放到多个数据库里面,从而将单台数据库的负载分散到多个数据库。

数据的切分可以分为垂直切分与水平切分两种切分模式。按照业务的不同,对表进行分类,不同业务的表切分到不同的数据库称为垂直切分;按照表中某个字段的特定规则将数据分散到多个库之中,每个表都包含部分数据,称为水平切分。水平切分可以理解为是按照数据行进行的切分,表中的一部分行切分到一个数据库,而另外的一部分行又切分到其他的数据库中,分布式数据库一般使用的是水平切分的方式。

垂直切分一般来说规则比较简单,实施比较方便,对于业务逻辑清晰,业务之间的耦合度较低的系统尤其适合。在湖南电信BSS3.0系统中就按照相对独立的业务垂直切分为受理中心数据库、账务中心数据库、计费中心数据库、策略中心数据库、客服中心数据库等。由于垂直切分是按照不同的业务的分类将表分散到不同的库,不可避免地存在一些业务表会过于庞大、单库读写性能与存储瓶颈的问题,例如经过垂直切分后的计费中心数据库依然存在单表数据量过大的问题,此时就需要进行进一步的水平拆分来做解决。

水平切分相对于垂直切分来说,由于要将同一个表中的不同数据拆分到不同的数据库中,拆分规则及后期的数据维护及数据访问也会更为复杂一些。在数据的水平切分过程中,数据容量和访问的均衡性是我们首要考量的因素,不均衡的数据分布和访问无法充分发挥数据拆分的能力,让访问体验变差,同时带来成本上的损耗。一般来说拆分字段区分度比较大,数据分布和访问相对会比较均衡,同时也需要考虑到某一个拆分值是否存在热点访问的问题。此外,事务边界越大或者单个sql所执行的数据分片数越大,那么系统的锁冲突概率越高,系统越难以扩展,性能越低。因此,若想将系统做到很好的扩展性,那么一个最重要的原则就是想办法划小事务边界,并尽可能让事务的边界限制在单台机器内。

3.1数据切分的原则

分表分库虽然能解决大表对数据库系统的压力,但它并不是万能的,也有一些不利之处,通过结合在湖南电信的应用实践,数据切分一般要遵守以下几个原则。

分片数量尽量少,分片尽量均匀分布在多个库上,因为一个查询SQL跨分片越多,则总体性能越差,只在必要的时候进行扩容,增加分片数量。

能不分片就不分片,800万行以内的表,不建议分片,通过合适的索引,读写分离等方式,可以很好地解决性能问题。

不到800万但跟大表(超800万的表)有关联查询的表也要拆分,在此称为大表关联表。大表关联表如何拆:小于100万的使用全局表;大于100万小于800万跟大表使用同样的拆分策略;无法跟大表使用相同规则的,可以考虑从iava代码上分步骤查询,不用关联查询,或者破例使用全局表。

拆分字段只能是一個字段,如果想按照两个字段拆分,必须新建一个冗余字段,冗余字段的值使用两个字段的值拼接而成(如大xE+年月拼成zone_yyyymm字段)。

分片规则需要慎重选择,分片规则的选择,需要考虑数据的增长模式,数据的访问模式,分片关联性问题,分片扩容问题以及数据热点问题。如果某个表的数据有明显的时间特征,比如订单、交易记录等,则他们通常比较合适用时间范围分片,因为具有时效性的数据,我们往往关注其近期的数据,查询条件中往往带有时间字段进行过滤,比较好的方案是,当前活跃的数据,采用跨度比较短的时间段进行分片,而历史性的数据,则采用比较长的跨度存储。总体上来说,分片的选择是取决于最频繁的查询SQL的条件。

3.2水平切分的常用算法

水平切分的算法根据分片键类型的不同主要有以下几种:

取模分片(PartitionByMod)是对整数型分片键进行十进制求模,根据模值对应到不同分片。适用于分片键是整数类型,分片键求余后的值均匀分布的场景。其特点是算法简单,性能高,由于分片键相邻的数据分散在不同的分片上故对多值、范围的查询支持较差。

字符串hashCode取模分片(PartitionByStringMod)是对字符型分片字段的值先进行hashcode()计算并取其绝对值,然后根据配置的分片数量求模得到最终的分片。由于是对字符串先hash再取模,数据分布较不均匀。

枚举分片(PartitionByFileMap)是根据配置文件中枚举的具体值(允许非数值)与分片号的对应关系和分片字段的值进行分片,当未找到对应分片时,进入到设定的默认分片。数据分布的均匀度取决于枚举值对应的记录是否分布均匀,较好的支持多值、范围的查询。电信有些业务数据需要按照省份或市县来做保存,而省份市县相对固定,适合于使用这个分片算法。

时间范围分片(PartitionByDat-eRange)是按照时间范围进行分片,超过分片数量后从第一个分片再次循环分片。适用于按时间范围进行存储的数据。

枚举分组取模分片(PartitionByEnumAndMod)是枚举+取模的组合分片方式,包含枚举键和取模键两个分片键,先通过枚举键将数据分配到不同的分组,再在分组里通过取模键对应到具体的分片。

4数据库中间件

要实现对应用透明的分布式数据库的访问,离不开数据库中间件。简单来说,数据库中间件就是介于数据库与应用之间,进行数据处理与交互的中间服务。由于对数据进行水平切分处理之后,原来一个表的数据现在分布到多个库的多个表里,应用不可避免的需要访问多个数据库的数据并进行汇聚处理。如果没有数据库中间件,那么应用将直接面对分片集群,数据源切换、事务处理、数据聚合都需要应用直接处理,原本该是专注于业务的应用,将会花大量的工作来处理分片后的问题。所以有了数据库中间件,应用只需要集中于业务处理,而数据聚合,事务,数据源切换都由中间件来完成,数据库中间件可以看作一个或多个数据库集群构成的逻辑库,而对实际应用来说,并不需要知道中间件的存在。

5电信自研的分布式数据库

5.1系统架构

电信自研的分布式数据库由统一数据访问层TeleUDAL及高可用数据库TeleDB两部分组成。TeleDB基于开源关系型数据库MySQL改造,提供高可靠的数据存储能力;数据访问基于开源数据库中间件Cobar改造,屏蔽数据库分库分表带来的访问难题。

系统架构图如图1所示。

从图1可看出,TeleUDAL主要由LVS、DBProxy、GiServer组件组成。

LVS为DBProxy提供服务注册发现及负载均衡功能,应用发送的请求通过LVS均衡分布到各个DBProxy上。

DBProxy是TeleUDAL的核心组件,是一个实现了mysql协议的Sever进程,前端用户可以把DBProxy看成数据库代理,可用mysql客户端工具或命令行方式直接访问,其后端以mysql原生協议与多个mysql数据库进行通信,也可以用jdbc协议与大多数主流数据库服务器通信,DBProxy的核心功能是分库分表并对应用层屏蔽分库分表带来的访问难题。

GiServer是切片索引服务进程,是为了提升非分片键查询(select语句)时的效率(避免广播查询)而开发的,与数据库的索引没有任何关系,是完全不同的两个概念,GiServer是切片索引数据的生产者,真正的消费者是DBProxy进程,假设客户表是以cust_id进行分表的,但应用需要通过客户身份证来查询客户信息,如果没有切片索引,则DBProxy会将查询语句广播到所有节点执行,接收到执行结果进行汇聚后再返回给应用,如果建立了切片索引,则DBProxy首先会根据身份证号码从切片索引中查询到对应的cust_id,再根据分片算法定位到cust_id对应的分片,这样就避免了广播查询。

除此之外,UDAL依赖的外部组件主要有zookeeper及分布式缓存,zookeeper用于存放DBProxy、GiServer的配置信息及全局序列数据,分布式缓存用于存放切片索引数据。

5.2关键概念

电信分布式数据库中涉及逻辑库、逻辑表、切片索引、全局序列等几个关键概念。

逻辑库(schema),对实际应用来说,并不需要知道中间件的存在,应用开发人员只需要知道数据库的概念,所以数据库中间件可以被看作一个或多个数据库集群构成的逻辑库。UDAL的逻辑库(schema),与MySQL中的Database(数据库)对应,一个逻辑库中定义了所包括的table。

逻辑表(table),对应用来说,所操作的表就是逻辑表,可以是数据切分后,分布多个分片库中,也可以不做切分,存放在单个分片中,在UDAL中逻辑表包括:单片表、分片表、全局表、库内分表四种类型的表。

单片表是相对分片表来说的,就是指那些不需要作数据切分的表,一个数据库中并不是所有表都很大,某些表是可以不用进行切分的。

分片表是指那些原有的很大数据的表,需要切分到多个数据库的表,这样,每个分片都有一部分数据,所有分片构成完整的数据。

全局表是在每个分片库都中保存一份同样数据的表,主要解决跨库关联查询问题。这类表的数据量一般较小,变化不频繁,如:字典、配置、工号、机表、区域等,其特点主要是变动不频繁,数据量总体变化不大且数据量较小,全局表的插入、更新操作会同步在所有节点上执行,全局表的查询操作,只从一个节点获取,全局表可以跟任何一个表进行JOIN操作。对全局表执行update、delete、insert等DML操作时,需要保障这些DML语句在所有节点同步执行成功,由于全局表的每条语句都需要分发到所有节点执行,这样就形成了跨节点分布式事务,在UDAL中我们采用事务补偿机制来保障全局表数据的最终一致性。DB-Proxy检测事务中的第一条DML语句是全局表时,会自动开启分布式事务如果有节点commit失败,DBProxy会进行自动补偿。

切片索引fgiserver)是一组非分片键和分片键的映射关系,目的是提升非分片键查询(select语句)时的效率,避免广播查询。当没有切片索引时,select语句中如果没有带分片键,db-proxy无法计算出分片节点,这样语句会广播到所有节点执行。如果有切片索引,先通过非分片键查询到分片键的值,根据分片键的值计算出路由节点,再把语句发送到相应的分片执行,避免了广播查询。GiServer的原理是基于mysql binlog技术,模拟自己为mysql slave,所以一定要开启mysql的binlog功能,并配置binlog模式为row.数据处理流程如图2所示。

全局序列是在整个逻辑库层面实现了全局唯一的序列。在分布式数据库场景下,一个逻辑库对应了多个物理数据库分片,逻辑库表的主键要求在所有物理库分片上都唯一,这样用数据库本身的机制生成序列号就无法满足业务的需求了,必须采用新的全局序列生成机制。我们TeleUDAL的实现原理是DBProxy从ZooKeeper上獲取序列段保存到本地内存,同时修改ZooKeeper上下一次获取序列段的起始值,本地内存中的序列用完后再从zk获取新的序列段。全局序列的使用与ora]ce的sequence使用类似,先创建好sequence,再通过select XXX.next-val获取序列值。为保证序列获取的效率,dbproxy会缓存一段序列,这样在一个集群中存在多个dbproxy的情况下不能保证序列是严格递增的。

5.3 TeleUDAL简单原理

TeleUDAL究竟是如何实现数据的水平拆分及对应用透明的数据访问的呢?下面简要说明其实现原理。

1)数据的拆分及存储

分片键是数据进行拆分的分片字段,是UDAL中数据分布和SQL路由的计算依据。UDAL中的数据按照拆分字段值,加上特定的算法进行计算,根据结果存储数据到对应分片。如图3所示,左表使用MEMBE_ID作为分片键,表中数据根据字符串hash取模算法分散到库1和2中。

2)SQL路由

当用户SQL到UDAL时,UDAL会理解整个SQL含义,然后按照拆分字段的值和执行策略将SQL路由到对应分区进行执行,如图4所示。

3)数据汇聚

如果一个SQL对应多个分片数据执行,UDAL会将各个分片返回的数据按照原始SQL语义进行合并,如图5所示。

5.4TdeDB梁构

TeleDB是中国电信基于开源MySQL5.7数据库系统自主开发的高可用数据库集群产品。在MYSQL基础上,额外开发了Gateway、keeper、Agen组件,对外提供高性能高可用、数据一致性的分布式数据库服务,大概架构如图7所示。

Keeper是TeleDB的调度器,监听zookeeper的特定路径,主要作用是用于监控底层主数据库与备数据库的可用状态、数据库同步延迟等一类信息;决定主从数据是否能够进行主从切换,控制主从切换的启动及操作过程。在生产环境中为保证KEEPER高可用,至少部署三台KEEPER在三台独立机上。

zookeeper是分布式一致性协议的一种开源实现,用于TeleDB组件中状态信息的保存,起到通信媒介的作用;一旦zookeeper崩溃,各个模块间的通信全部中断。为保证zookeeper高可用,至少部署三台zookeeper在三台独立机上。

Agent用于收集底层DB服务器的状态信息,并将相关信息写入zookeeper。DB服务器状态信息包括底层数据库状态信息(是否可读写),主从数据复制延迟、服务器负载、磁盘使用使用情况等信息。

DB层是数据库节点组,由MySQL数据库引擎模块以及监控和信息采集系统AGENT两个部分组成,一个数据库节点组(SET)包括一个主节点(Master)、若干备节点(slave)I,一般是一主两从,SET通过心跳监控和信息采集模块(agent)监控,确保集群的健壮性;在分布式架构下,若干个数据库节点组(SET)可以提供一个“逻辑统一,物理分散”分布式数据库实例。

5.5TeleDB核心功能

TeleDB在开源的MySQL的基础上,对主从同步、性能和可靠性等多个方面做了一定的改进。

1)支持在事务commit前等待ACK,提高主备库同步可靠性。

TeleDB相对于MySQL5.7之前的版本增加了rDl-semi_sync_master_wait_point参数来控制半同步复制模式下主库在返回给会话事务成功之前提交事务的方式。

该参数有两个值AFrER_COMMIT,AFrER_SYNC。AF-TER_COMMIT是master将每个事务写入binlog,传递到slave刷新到磁盘(relay 10g),同时主库提交事务。master等待slave反馈收到relaylog,只有收到ACK后master才将commitOK结果反馈给客户端,由于主库在备库返回ACK信号之前就提交了事务,故存在主备库数据不一致的风险;而AFTER_SYNC则是master将每个事务写入binlog,传递到slave刷新到磁盘(relaylog)。master等待slave反馈接收到relaylog的ack之后,再提交事务并且返回commit OK结果给客户端。即使主库crash,所有在主库上已经提交的事务都能保证已经同步到slave的relaylog中,因此AFTER_SYNC模式同步的可靠性更高,TeleDB默认采用该模式。

2)实现了发送binlog和接受ack的异步化,提高主备库同步性能。

以前版本的半同步的性能受限于dump thread,原因是dumpthread承担了两份不同且又十分频繁的任务:传送binlog给slave,还需要等待slave反馈信息,而且这两个任务是串行的,dump thread必须等待slave返回之后才会传送下一个events事务。dump thread已然成为整个半同步提高性能的瓶颈。在高并发业务场景下,这样的机制会影响数据库整体的TPS。在TeleDB中,实现了发送binlog和接受ack的异步化,提高了主从同步的性能。

3)控制半同步主库超时时间,实现高性能与高可靠灵活控制。

TeleDB版本在MySQL 5.7基础上通过调整rpl_semi_sync_master_timeout参数,来控制半同步主库超时时间,以便运维人员在性能与可靠性两者之间进行权衡。在通常的生产运营环境下,通过将该参数调整为较大的值,可以达到高可靠即强同步的效果;而在其他一些对数据可靠性不那么敏感,而对性能要求更高的场合,则可以将此参数调小。

4)使用线程池技术,提高连接效率。

TeleDB拋弃了MySQL传统每连接每线程的连接模式,这种连接模式会导致巨大的系统开销进而影响整个性能。因此,TeleDB通过扩展MySQL线程池,使用线程池技术来解决最大连接数限制问题以及过多线程带来的系统开销。

5)提升高并发场景下的性能稳定性。

MySQL官方版默认使用glibc作为mallc的动态库,在高并发情况下,大量连接连到数据库,而在这些连接结束释放资源后,MvsQL会导致cpu sys值升高,使数据库性能恶化。针对此问题,TeleDB给出两种方案:增强线程池功能,跟主流开源线程池版本例如Percona、MariaDB等相比增加了线程池线程Cache功能;修改底层内存分配库,替代默认使用系统glibc库。以上两种方案都可以解决MySQL官方版本使用glibc高并发场景sys升高的问题,没有再出现sys飙高导致性能急剧下降的情况。

通过以上几个方面的改进,TeleDB在高可靠、高连接、高并发、高吞吐等访问场景下表现出极强的稳定性,比官方MySQL具有明显的优势。

6分布式数据库在湖南电信的应用

2018年,湖南电信启动以分布式数据库为核心的企业级PaaS平台建设,到2019年7月为止,已经完成服务开通系统、自动激活系统、支付中心的改造迁移工作,预计到2019年底完成客户服务中心、能力开放平台等其余15个系统的改造迁移工作,到2020年完成湖南电信核心BSS3.0系统的迁移改造工作。目标是在未来几年逐步实现省内IT系统、网管系统、业务系统的分布式改造,实现统一平台、统一运营。

通过使用TeleUDAL和TeleDB分布式数据库,迁移后支付中心的SQL执行平均耗时由15ms减少到4ms,SQL执行效率提升275%,服务开通系统每分钟CRM取单峰值,由之前的1333笔提升到5552笔,性能提升316%;移动电话派发自动激活,每分钟取单峰值由之前的582笔提升到1161笔,性能提升99.5%。系统改造后,效果提升明显,充分证明TeleUDAL和TeleDB组成的分布式数据库系统的稳定、可靠、高性能,实现了容量和服务能力的可弹性伸缩,可轻松应对高并发的实时交易场景。

7结论

面对海量数据的存储、处理、访问的难题,中国电信基于开源组件开发了TeleUDAL和TeleDB分布式数据库,TeleUDAL通过对数据的水平切分,将海量数据分散到多个物理上独立而逻辑上统一的数据库里,解决数据存储和并发访问问题;通过SQL路由和数据汇聚技术解决透明数据访问的问题。TeleDB通过搭建一主两从的集群,解决数据的可靠存储问题,通过对开源Mysql的改进,提高主备库同步的可靠性及性能。最终解决了电信企业海量交易型业务数据的存储和高效访问的难题,使湖南电信能够将传统的运营商支撑系统转型为新型的互联网IT架构的系统,提升企业通信服务水平。