阿里巴巴TDDL

注意 此文章为完全转载 为了博主本身方便查看 。另附 原博客地址:http://gao-xianglong.iteye.com/blog/2019729/ 支持博主 支持原创!

目录

一、互联网当下的数据库拆分过程

二、TDDL的架构原型

三、下载TDDL的Atom层和Group层源代码

四,Diamond和TDDL结合配置示例

 

一、互联网当下的数据库拆分过程

对于一个刚上线的互联网项目来说,由于前期活跃用户数量并不多,并发量也相对较小,所以此时企业一般都会选择将所有数据存放在一个数据库中进行访问操作。但随着后续的市场推广力度不断加强,用户数量和并发量不断上升,这时如果仅靠一个数据库来支撑所有访问压力,几乎是在自寻死路。所以一旦到了这个阶段,大部分Mysql DBA就会将数据库设置成读写分离状态,也就是一个Master节点对应多个Salve节点。经过Master/Salve模式的设计后,完全可以应付单一数据库无法承受的负载压力,并将访问操作分摊至多个Salve节点上,实现真正意义上的读写分离。但大家有没有想过,单一的Master/Salve模式又能抗得了多久呢?如果用户数量和并发量出现量级上升,单一的Master/Salve模式照样抗不了多久,毕竟一个Master节点的负载还是相对比较高的。为了解决这个难题,Mysql DBA会在单一的Master/Salve模式的基础之上进行数据库的垂直分区(分库)。所谓垂直分区指的是可以根据业务自身的不同,将原本冗余在一个数据库内的业务表拆散,将数据分别存储在不同的数据库中,同时仍然保持Master/Salve模式。经过垂直分区后的Master/Salve模式完全可以承受住难以想象的高并发访问操作,但是否可以永远高枕无忧了?答案是否定的,一旦业务表中的数据量大了,从维护和性能角度来看,无论是任何的CRUD操作,对于数据库而言都是一件极其耗费资源的事情。即便设置了索引,仍然无法掩盖因为数据量过大从而导致的数据库性能下降的事实,因此这个时候Mysql DBA或许就该对数据库进行水平分区(分表,sharding),所谓水平分区指的是将一个业务表拆分成多个子表,比如user_table0、user_table1、user_table2。子表之间通过某种契约关联在一起,每一张子表均按段位进行数据存储,比如user_table0存储1-10000的数据,而user_table1存储10001-20000的数据,最后user_table3存储20001-30000的数据。经过水平分区设置后的业务表,必然能够将原本一张表维护的海量数据分配给N个子表进行存储和维护,这样的设计在国内一流的互联网企业比较常见,如图1-1所示:

 

图1-1 水平分区

 

上述笔者简单的讲解了数据库的分库分表原理。接下来请大家认真思考下。原本一个数据库能够完成的访问操作,现在如果按照分库分表模式设计后,将会显得非常麻烦,这种麻烦尤其体现在访问操作上。因为持久层需要判断出对应的数据源,以及数据源上的水平分区,这种访问方式我们称之为访问“路由”。按照常理来说,持久层不应该负责数据访问层(DAL)的工作,它应该只关心one to one的操作形式,所以淘宝的TDDL框架诞生也就顺其自然了。

 

二、TDDL的架构原型

淘宝根据自身业务需求研发了TDDL(Taobao Distributed Data Layer)框架,主要用于解决分库分表场景下的访问路由(持久层与数据访问层的配合)以及异构数据库之间的数据同步,它是一个基于集中式配置的JDBC DataSource实现,具有分库分表、Master/Salve、动态数据源配置等功能。

就目前而言,许多大厂也在出一些更加优秀和社区支持更广泛的DAL层产品,比如Hibernate Shards、Ibatis-Sharding等。如果你要问笔者还为什么还要对TDDL进行讲解,那么笔者只能很无奈的表示公司要这么干,因为很多时候技术选型并不是笔者说了算,而是客户说了算。当笔者费劲所有努力在google上寻找TDDL的相关使用说明和介绍时,心里一股莫名的火已经开始在蔓延,对于更新缓慢(差不多一年没更新过SVN),几乎没社区支持(提问从不响应)的产品来说,除了蜗居在企业内部,必定走不了多远,最后的结局注定是悲哀的。好了,既然抱怨了一番,无论如何还是要坚持讲解完。TDDL位于数据库和持久层之间,它直接与数据库建立交道,如图1-2所示:

 

图1-2 TDDL所处领域模型定位

 

传说淘宝很早以前就已经对数据进行过分库分表处理,应用层连接多个数据源,中间有一个叫做DBRoute的技术对数据库进行统一的路由访问。DBRoute对数据进行多库的操作、数据的整合,让应用层像操作一个数据源一样操作多个数据库。但是随着数据量的增长,对于库表的分法有了更高的要求,例如,你的商品数据到了百亿级别的时候,任何一个库都无法存放了,于是分成2个、4个、8个、16个、32个……直到1024个、2048个。好,分成这么多,数据能够存放了,那怎么查询它?这时候,数据查询的中间件就要能够承担这个重任了,它对上层来说,必须像查询一个数据库一样来查询数据,还要像查询一个数据库一样快(每条查询要求在几毫秒内完成),TDDL就承担了这样一个工作(其他DAL产品做得更好),如图1-3所示:

 

图1-3 TDDL分库分表查询策略

 

上述笔者描述了TDDL在分库分表环境下的查询策略,那么接下来笔者有必要从淘宝官方copy它们自己对TDDL优点的一些描述,真实性不敢保证,毕竟没完全开源,和社区零支持,大家看一看就算了,别认真。

淘宝人自定的TDDL优点:

1、数据库主备和动态切换;
2、带权重的读写分离;
3、单线程读重试;
4、集中式数据源信息管理和动态变更;
5、剥离的稳定jboss数据源;
6、支持mysql和oracle数据库;
7、基于jdbc规范,很容易扩展支持实现jdbc规范的数据源;
8、无server,client-jar形式存在,应用直连数据库;
9、读写次数,并发度流程控制,动态变更;
10、可分析的日志打印,日志流控,动态变更;

 

注意

TDDL必须要依赖diamond配置中心(diamond是淘宝内部使用的一个管理持久配置的系统,目前淘宝内部绝大多数系统的配置)。

 

接下来,笔者将会带领各位一起分析TDDL的体系架构。TDDL其实主要可以划分为3层架构,分别是Matrix层、Group层和Atom层。Matrix层用于实现分库分表逻辑,底层持有多个Group实例。而Group层和Atom共同组成了动态数据源,Group层实现了数据库的Master/Salve模式的写分离逻辑,底层持有多个Atom实例。最后Atom层(TAtomDataSource)实现数据库ip,port,password,connectionProperties等信息的动态推送,以及持有原子的数据源分离的JBOSS数据源)。

 

图1-4 TDDL体系结构

 

       章节的最后,我们还需要对TDDL的原理进行一次剖析。因为我们知道持久层只关心对数据源的CRUD操作,而多数据源的访问,并不应该由它来关心。也就是说TDDL透明给持久层的数据源接口应该是统一且“单一”的,至于数据库到底如何分库分表,持久层无需知道,也无需编写对应的SQL去实行应对策略。这个时候对TDDL一些疑问就出现了,TDDL需要对SQL进行二次解析和拼装吗?答案是不解析仅拼装。说白了TDDL只需要从持久层拿到发出的SQL

再按照一些分库分表条件,进行特定的SQL扩充以此满足访问路路由操作。

 

以下是淘宝团队对TDDL的官方原理解释:

1、TDDL除了拿到分库分表条件外,还需要拿到order by、group by、limit、join等信息,SUM、

MAX、MIN等聚合函数信息,DISTINCT信息。具有这些关键字的SQL将会在单库和多库情况下进行,语义是不同的。TDDL必须对使用这些关键字的SQL返回的结果做出合适的处理;

2、TDDL行复制需要重新拼写SQL,带上sync_version字段;

3、不通过sql解析,因为TDDL遵守JDBC规范,它不可能去扩充JDBC规范里面的接口,所以只能通过SQL中加额外的字符条件(也就是HINT方式)或者ThreadLocal方式进行传递,前者使SQL过长,后者难以维护,开发debug时不容易跟踪,而且需要判定是在一条SQL执行后失效还是1个连接关闭后才失效;

4、TDDL现在也同时支持Hint方式和ThreadLocal方式传递这些信息;

 

三、下载TDDL的Atom层和Group层源代码

         前面我们谈及了TDDL的动态数据源主要由2部分构成,分别是Atom和Group。Group用于实现数据库的Master/Salve模式的写分离逻辑,而Atom层则是持有数据源。非常遗憾的TDDL中还有一层叫做Matrix,该层是整个TDDL最为核心的地方,淘宝也并没有对这一层实现开源,而Matrix层主要是建立在动态数据源之上的分库分表实现。换句话说,TDDL是基于模块化结构的,开发人员可以选用TDDL中的部分子集。

       大家可以从淘宝的TaoCode上下载TDDL的源码带,然后进行构件的打包。TDDL的项目主要是基于Maven进行管理的,所以建议大家如果不了解Maven的使用,还是参考下笔者的博文《Use Maven3.x》。

       大家下载好TDDL的源代码后,通过IDE工具导入进来后可以发现,开源的TDDL的工程结构有如下几部份组成:

tddl-all –

—tbdatasource

—tddl-atom-datasource

—tddl-common

—tddl-group-datasource

—tddl-interact

—tddl-sample

 

大家可以使用Maven的命令“mvn package“将TDDL的源代码打包成构件。如果你的电脑上并没有安装Maven的插件到不是没有办法实现构件打包,你可以使用eclipse的导出命令,将源代码导出成构件形式也可以。

 

四、Diamond简介

       使用任何一种框架都需要配置一些配置源信息,毕竟每一种框架都有自己的规范,使用者务必遵守这些规范来实现自己的业务与基础框架的整合。自然TDDL也不例外,也是有配置信息需要显式的进行配置,在TDDL中,配置可以基于2种方式,一种是基于本地配置文件的形式,另外一种则是基于Diamond的形式进行配置,在实际开发过程中,由于考虑到配置信息的集中管理所带来的好处,大部分开发人员愿意选择将TDDL的配置信息托管给Diamond,所以本文还是以Diamond作为TDDL的配置源。

       diamond是淘宝内部使用的一个管理持久配置的系统,它的特点是简单、可靠、易用,目前淘宝内部绝大多数系统的配置,由diamond来进行统一管理。diamond为应用系统提供了获取配置的服务,应用不仅可以在启动时从diamond获取相关的配置,而且可以在运行中对配置数据的变化进行感知并获取变化后的配置数据。

 

五、Diamond的安装和使用

       Diamond和TDDL不同,它已经实现了完全意义上的开源。大家可以从淘宝的TaoCode

上下载Diamond的源代码,SVN下载地址为http://code.taobao.org/svn/diamond/trunk。当大家成功下载好Diamond的源代码后,我们接下来就需要开始Diamond的环境搭建工作。

       首先我们需要安装好Mysql数据库,以root用户登录,建立用户并赋予权限,建立数据库,然后建表,语句分别如下:

create database diamond;

grant all on diamond.* to zh@’%’  identified by ‘abc’;

use diamond

create table config_info (

‘id’ bigint(64) unsigned NOT NULL auto_increment,

‘data_id’ varchar(255) NOT NULL default ’ ’,

‘group_id’ varchar(128) NOT NULL default ’ ’,

‘content’ longtext NOT NULL,

‘md5′ varchar(32) NOT NULL default ’’,

‘gmt_create’ datetime NOT NULL default ’2010-05-05 00:00:00′,

‘gmt_modified’ datetime NOT NULL default ’2010-05-05 00:00:00′,

PRIMARY KEY  (‘id’),

UNIQUE KEY ‘uk_config_datagroup’ (‘data_id’,'group_id’));

 

完成后,请将数据库的配置信息(IP,用户名,密码)添加到diamond-server工程的src/resources/jdbc.properties文件中的db.url,db.user,db.password属性上面,这里建立的库名,用户名和密码,必须和jdbc.properties中对应的属性相同。

tomcat是Damond的运行容器,在diamond-server源代码根目录下,执行mvn clean package -Dmaven.test.skip,成功后会在diamond-server/target目录下生成diamond-server.war。打包完成后,将diamond-server.war放在tomcat的webapps目录下。最后启动tomcat,即启动了Diamond。

http server

http server用来存放diamond server等地址列表,可以选用任何http server,这里以tomcat为例。

安装tomcat的步骤请参开tomcat官方文档,注意,如果http server和diamond server安装在一台机器上,请修改http server的端口,避免冲突。

修改完端口后,请将diamond-utils工程下的com.taobao.diamond.common.Constants类中的DEFAULT_PORT常量修改成对应的端口号。

安装完成后,请在tomcat的webapps下建立文件夹diamond-server和pushit-server,diamond-server中再建立diamond文件,文件内容是diamond-server的地址列表,一行一个地址,地址为ip


 

六、TDDL+Diamond

示例使用

Tddl动态数据源的开源代码中,有一个tddl-sample工程,该工程演示了如何使用tddl动态数据源.但需要一些配置支持,以下说明需要做的配置.

AtomDataSource示例使用说明

1.创建mysql库和表

(1).建库qatest_normal_0:

dropdatabaseifexistsqatest_normal_0;

CREATEDATABASE`qatest_normal_0`

(2).在库qatest_normal_0中建表normaltbl_0001

USEqatest_normal_0;

CREATETABLE`normaltbl_0001`(

`pk`int(11)NOTNULL,

`id`int(11)DEFAULTNULL,

`gmt_create`dateDEFAULT’2010-12-17′,

`name`varchar(30)DEFAULTNULL,

`floatCol`float(9,3)DEFAULT’0.000′,

PRIMARYKEY(`pk`)

)ENGINE=InnoDBDEFAULTCHARSET=latin1;

(3).在库qatest_normal_0中创建tddl用户,授予读写数据库权限

CREATEUSER’tddl’@'%’IDENTIFIEDBY’tddl’;

GRANTInsert,Update,Select,DeleteONqatest_normal_0.*TO’tddl’@'%’;

2.在diamond中配置Atom数据源

Global配置

dataId:com.taobao.tddl.atom.global.qatest_normal_0

group:DEFAULT_GROUP

content:

ip=127.0.0.1

port=3306

dbName=qatest_normal_0

dbType=mysql

dbStatus=RW

App配置

dataId:com.taobao.tddl.atom.app.tddl_sample.qatest_normal_0

group:DEFAULT_GROUP

content:

userName=tddl

minPoolSize=1

maxPoolSize=2

idleTimeout=10

blockingTimeout=5

preparedStatementCacheSize=15

connectionProperties=characterEncoding=gbk

User配置(dataId最后一段’.tddl’和用户名紧相关,如果数据库用户名不是tddl,请修改这个dataId)

dataId:com.taobao.tddl.atom.passwd.qatest_normal_0.mysql.tddl

group:DEFAULT_GROUP

content:

encPasswd=xxxxxxx(密文,请用tddl-atom-datasource工程下的JbossPasswordDecode加密下明文密码)

3.添加TDDL依赖(建议使用maven,settings.xml文件绑定淘宝开源maven库,见附录)

<dependency>

<groupId>com.taobao.tddl</groupId>

<artifactId>tddl-group-datasource</artifactId>

<version>3.0.1.5.taobaocode-SNAPSHOT</version>

</dependency>

<dependency>

<groupId>com.taobao.tddl</groupId>

<artifactId>tddl-atom-datasource</artifactId>

<version>3.0.1.5.taobaocode-SNAPSHOT</version>

</dependency>

4.在代码中调用AtomDataSource

TAtomDataSourcetAtomDataSource=newTAtomDataSource();
tAtomDataSource.setAppName(appName);//appName是当前业务的名称
tAtomDataSource.setDbKey(dbKey);//dbKey是dba告知业务的当前数据库实例的名字(用于标志唯一的数据库)
TAtomDataSource.init();

GroupDataSource示例使用说明

1.在mysql数据库中创建库和表(如果atomds示例中已经创建的库表,则不需要再创建)

(1)建库qatest_normal_0

dropdatabaseifexistsqatest_normal_0;

CREATEDATABASE`qatest_normal_0`

(2)在库qatest_normal_0中建表normaltbl_0001

USEqatest_normal_0;

CREATETABLE`normaltbl_0001`(

`pk`int(11)NOTNULL,

`id`int(11)DEFAULTNULL,

`gmt_create`dateDEFAULT’2010-12-17′,

`name`varchar(30)DEFAULTNULL,

`floatCol`float(9,3)DEFAULT’0.000′,

PRIMARYKEY(`pk`)

)ENGINE=InnoDBDEFAULTCHARSET=latin1;

(3)建库qatest_normal_0_bac

dropdatabaseifexistsqatest_normal_0_bac;

CREATEDATABASE`qatest_normal_0_bac`;

(4)在库qatest_normal_0_bac中建表normaltbl_0001

USEqatest_normal_0_bac;

CREATETABLE`normaltbl_0001`(

`pk`int(11)NOTNULL,

`id`int(11)DEFAULTNULL,

`gmt_create`dateDEFAULT’2010-12-17′,

`name`varchar(30)DEFAULTNULL,

`floatCol`float(9,3)DEFAULT’0.000′,

PRIMARYKEY(`pk`)

)ENGINE=InnoDBDEFAULTCHARSET=latin1;

(5).在以上两个数据库中创建tddl用户,授予读写数据库权限

CREATEUSER’tddl’@'%’IDENTIFIEDBY’tddl’;

GRANTInsert,Update,Select,DeleteONqatest_normal_0.*TO’tddl’@'%’;

GRANTInsert,Update,Select,DeleteONqatest_normal_0_bac.*TO’tddl’@'%’;

2.在diamond中配置Group数据源

(1)在diamond中配置Group一组对等的数据的读写权重

dataId:com.taobao.tddl.jdbc.group_V2.4.1_group_sample

group:DEFAULT_GROUP

content:

qatest_normal_0:r10w10,qatest_normal_0_bac:r10w0

(2)在diamond中配置Atom(qatest_normal_0)数据源

Global配置

dataId:com.taobao.tddl.atom.global.qatest_normal_0

group:DEFAULT_GROUP

content:

ip=127.0.0.1

port=3306

dbName=qatest_normal_0

dbType=mysql

dbStatus=RW

App配置

dataId:com.taobao.tddl.atom.app.tddl_sample.qatest_normal_0

group:DEFAULT_GROUP

content:

userName=tddl

minPoolSize=1

maxPoolSize=2

idleTimeout=10

blockingTimeout=5

preparedStatementCacheSize=15

connectionProperties=characterEncoding=gbk

User配置(dataId最后一段’.tddl’和用户名紧相关,如果数据库用户名不是tddl,请修改这个dataId)

dataId:com.taobao.tddl.atom.passwd.qatest_normal_0.mysql.tddl

group:DEFAULT_GROUP

content:

encPasswd=xxxxxxx(密文,请用tddl-atom-datasource工程下的JbossPasswordDecode加密下明文密码)

(3)在diamond中配置Atom(qatest_normal_0_bac)数据源

Global配置

dataId:com.taobao.tddl.atom.global.qatest_normal_0_bac

group:DEFAULT_GROUP

content:

ip=127.0.0.1

port=3306

dbName=qatest_normal_0_bac

dbType=mysql

dbStatus=WR

App配置

dataId:com.taobao.tddl.atom.app.tddl_sample.qatest_normal_0_bac

group:DEFAULT_GROUP

content:

userName=tddl

minPoolSize=1

maxPoolSize=2

idleTimeout=10

blockingTimeout=5

preparedStatementCacheSize=15

connectionProperties=characterEncoding=gbk

User配置(dataId最后一段’.tddl’和用户名紧相关,如果数据库用户名不是tddl,请修改这个dataId)

dataId:com.taobao.tddl.atom.passwd.qatest_normal_0_bac.mysql.tddl

group:DEFAULT_GROUP

content:

encPasswd=xxxxxxx(密文,请用tddl-atom-datasource工程下的JbossPasswordDecode加密下明文密码)

3.添加TDDL依赖

<dependency>

<groupId>com.taobao.tddl</groupId>

<artifactId>tddl-group-datasource</artifactId>

<version>3.0.1.5.taobaocode-SNAPSHOT</version>

</dependency>

<dependency>

<groupId>com.taobao.tddl</groupId>

<artifactId>tddl-atom-datasource</artifactId>

<version>3.0.1.5.taobaocode-SNAPSHOT</version>

</dependency>

4.在代码中调用GroupDataSource

TGroupDataSourceds=newTGroupDataSource(dbGroupKey,appName);
ds.init();

附录

请修改MAVEN/conf/settings.xml文件,确保使用正确的MavenRepository。

目前我们将Tddl动态数据源发布在淘蝌蚪的mavenrepository中。

<?xmlversion=”1.0″encoding=”UTF-8″?>

<settingsxmlns=”http://maven.apache.org/SETTINGS/1.0.0″

xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”

xsi:schemaLocation=”

http://maven.apache.org/SETTINGS/1.0.0

http://maven.apache.org/xsd/settings-1.0.0.xsd”>

……

<servers>

<server>

<id>taocodeReleases</id>

<username>admin</username>

<password>admintaocode321</password>

</server>

<server>

<id>taocodeSnapshots</id>

<username>admin</username>

<password>admintaocode321</password>

</server>

</servers>

<profiles>

……

<profile>

<id>opensource</id>

<repositories>

<repository>

<id>taocodeReleases</id>

<name>taocodenexus</name>

<url>http://mvnrepo.code.taobao.org/nexus/content/repositories/releases/</url>

</repository>

<repository>

<id>taocodeSnapshots</id>

<name>taocodenexus</name>

<url>http://mvnrepo.code.taobao.org/nexus/content/repositories/snapshots/</url>

</repository>

</repositories>

</profile>

</profiles>

……

<activeProfiles>

<activeProfile>opensource</activeProfile>

</activeProfiles>

</settings>



  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值