阿里巴巴数据库分库分表的实践

2019-01-31 SKY 互联网
浏览

 1、阿里巴巴分布式数据层平台发展和演变

业务数据从原来的单库单表模式变成了数据被拆分到多个数据库,甚至多个表中,如果在数据访问层做一下功能的封装和管控,所有分库分表的逻辑和数据的跨库操作都交给应用的开发人员来实现,则对开发人员的要求变得相对高一点,稍有不慎,可能会对平台的业务包括数据带来较大的影响。

在2006年阿里巴巴B2B团队以开源方式研发了Cobar这一关系型数据的分布式处理系统。该系统在很大程度上解决了最初使用Oracle数据库因为存储数据变得越来越大带来的扩展性问题,并且为开发人员提供了一个使用相对简单的用户体验,在当时Cobar平均每天处理近50亿次的SQL操作。但随着阿里巴巴业务场景越来越复杂,Cobar平台功能上的约束对满足某些业务场景显得力不从心,例如:

1)不支持跨库情况下的连接、分页、排序、子查询操作。

2)SET语句执行会被忽略,处理事务和字符集设置除外。

3)分库情况下,insert语句必须包含拆分字段列名。

4)分库情况下,update语句不能更新拆分字段的值。

5)不支持SAVEPOINT操作。

6)使用JDBC时,不支持rewriteBatchedStatements=true参数设置(默认为false)。

7)使用JDBC时,不支持useServerPrepStmts=true参数设置(默认为false)。

8)使用JDBC时,BLOB、BINARY、VARBINARY字段不能使用setBlob()或setBinaryStream()方法设置参数。

2008年阿里巴巴内部基于淘宝业务发展的需要,在Cobar的基础上重新研发了分布式数据层框架TDDL(Taobao Distributed Data Layer,外号:头都大了),针对分库分表场景,提供了对各种业务场景的支持更加完善,开发人员体验更加友好,管控能力大幅提升。

目前TDDL已经成为阿里巴巴集团内部业务默认使用的分布式数据层中间件,支撑着今天阿里巴巴上千个应用,平均每天SQL调用超千亿次。从架构角度(如图5-3所示),TDDL沿袭了Cobar之前在应用和后端数据库之间的定位,通过增加对SQL的解析实现了更为精准的路由控制,以及对跨库join、统计等计算的支持,弥补了之前Cobar在功能上的约束和限制,成为一个完整支持SQL语法兼容的平台。

阿里巴巴数据库分库分表的实践

图5-3TDDL架构示意图

三层数据源每层都按JDBC规范实现,使得对前端应用没有任何代码侵入。

Matrix层(TDataSource)实现分库分表逻辑,底下持有多个GroupDs实例。

Group层(TGroupDataSource)实现数据库的主备/读写分离逻辑,底下持有多个AtomDs实例。

Atom层(TAtomDataSource)实现数据库连接(ip、port、password、connec-

tionProperties)等信息的动态推送,持有原子的数据源。

通过TDDL实现一次来自应用的SQL请求,完整的交互流程(如图5-4所示)中体现了各个服务组件所起到的作用。

阿里巴巴数据库分库分表的实践

图5-4TDDL针对一次SQL请求完整处理流程

正是有了这样的架构和设计,特别是增加了对SQL语义的解析,使得TDDL相比之前的Cobar在功能上提升了一个新的层级,对于Cobar不支持的跨库数据聚合、子查询、group by、order by等特性都有了很好的支持,从而成为在分库分表技术业界被很多技术同仁认可的一套分布式数据层框架,总结来说,TDDL提供了以下优点:

 数据库主备和动态切换。

 带权重的读写分离。

 单线程读重试。

 集中式数据源信息管理和动态变更。

 支持MySQL和Oracle数据库。

 基于JDBC规范,很容易扩展支持实现JDBC规范的数据源。

 无Server、client-jar形式存在,应用直连数据库。

 读写次数,并发度流程控制,动态变更。

 可分析的日志打印,日志流控,动态变更。

随着阿里巴巴集团业务的多元化,特别是对于除电商领域以外业务的不断扩展和并购,TDDL这种无Server的模式对于故障的定位和对运行环境的要求(必须是阿里巴巴内部服务环境),支持这些新兴业务有了不少困难,所以在2014年,阿里巴巴已经研发出新一代分布式数据库产品DRDS(Distributed Relational Database Service),该产品相比TDDL在业务场景的支持、故障的定位、运维管控等方面又有了一个全面的提升,今天DRDS已经成为阿里云上用于解决关系型数据库线性扩展问题的标准云产品,服务了几百家阿里巴巴集团外部的客户。

2、数据尽可能平均拆分

不管是采用何种分库分表框架或平台,其核心的思路都是将原本保存在单表中太大的数据进行拆分,将这些数据分散保存到多个数据库的多个表中,避免因为单表数据太大给数据的访问带来读写性能的问题。所以在分库分表场景下,最重要的一个原则就是被拆分的数据尽可能的平均拆分到后端的数据库中,如果拆分得不均匀,还会产生数据访问热点,同样存在热点数据因为增长过快而又面临数据单表数据过大的问题。

而对于数据以什么样的维度进行拆分,大家看到很多场景中都是对业务数据的ID(大部分场景此ID是以自增的方式)进行哈希取模的方式将数据进行平均拆分,这个简单的方式确实在很多场景下都是非常合适的拆分方法,但并不是在所有的场景中这样拆分的方式都是最优选择。也就是说数据如何拆分并没有所谓的金科玉律,更多的是需要结合业务数据的结构和业务场景来决定。

下面以大家最熟悉的电商订单数据拆分为例,订单是任何一个电商平台中都会有的业务数据,每个淘宝或天猫用户在平台上提交订单后都会在平台后端生成订单相关的数据,一般记录一条订单数据的数据库表结构如图5-5所示。

订单数据主要由三张数据库表组成,主订单表对应的就是用户的一个订单,每提交一次都会生成一个主订单表的数据。在有些情况下,用户可能在一个订单中选择不同卖家的商品,而每个卖家又会按照该订单中是自己提供的商品计算相关的商品优惠(比如满88元免快递费)以及安排相关的物流配送,所以会出现子订单的概念,即一个主订单会由多个子订单组成,而真正对应到具体每个商品的订单信息,则是保存在订单详情表中。

阿里巴巴数据库分库分表的实践

图5-5 订单相关数据表结构示意