[转] 淘宝数据库分布式代理层TDDL剖析



TDDL

淘宝根据自己的业务特点开发了TDDL(Taobao Distributed Data Layer 外号:头都大了 ©_Ob)框架,主要解决了分库分表对应用的透明化以及异构数据库之间的数据复制,它是一个基于集中式配置的 jdbc datasource实现,具有主备,读写分离,动态数据库配置等功能。
TDDL所处的位置(tddl通用数据访问层,部署在客户端的jar包,用于将用户的SQL路由到指定的数据库中):

淘宝很早就对数据进行过分库的处理, 上层系统连接多个数据库,中间有一个叫做DBRoute的路由来对数据进行统一访问。DBRoute对数据进行多库的操作、数据的整合,让上层系统像操作一个数据库一样操作多个库。但是随着数据量的增长,对于库表的分法有了更高的要求,例如,你的商品数据到了百亿级别的时候,任何一个库都无法存放了,于是分成2个、4个、8个、16个、32个……直到1024个、2048个。好,分成这么多,数据能够存放了,那怎么查询它?这时候,数据查询的中间件就要能够承担这个重任了,它对上层来说,必须像查询一个数据库一样来查询数据,还要像查询一个数据库一样快(每条查询在几毫秒内完成),TDDL就承担了这样一个工作。在外面有些系统也用DAL(数据访问层) 这个概念来命名这个中间件。
下图展示了一个简单的分库分表数据查询策略:

主要优点:
1.数据库主备和动态切换
2.带权重的读写分离
3.单线程读重试
4.集中式数据源信息管理和动态变更
5.剥离的稳定jboss数据源
6.支持mysql和oracle数据库
7.基于jdbc规范,很容易扩展支持实现jdbc规范的数据源
8.无server,client-jar形式存在,应用直连数据库
9.读写次数,并发度流程控制,动态变更
10.可分析的日志打印,日志流控,动态变更
TDDL必须要依赖diamond配置中心(diamond是淘宝内部使用的一个管理持久配置的系统,目前淘宝内部绝大多数系统的配置,由diamond来进行统一管理,同时diamond也已开源)。
TDDL动态数据源使用示例说明:http://rdc.taobao.com/team/jm/archives/1645
diamond简介和快速使用:http://jm.taobao.org/tag/diamond%E4%B8%93%E9%A2%98/
TDDL源码:https://github.com/alibaba/tb_tddl 
TDDL复杂度相对较高。当前公布的文档较少,只开源动态数据源,分表分库部分还未开源,还需要依赖diamond,不推荐使用。
终其所有,我们研究中间件的目的是使数据库实现性能的提高。具体使用哪种还要经过深入的研究,严谨的测试才可决定。







剖析淘宝 TDDL ( TAOBAO DISTRIBUTE DATA LAYER )

注:本文部分内容引用 本人 博客 http://gao-xianglong.iteye.com/blog/1973591

 

前言

在开始讲解淘宝的 TDDL(Taobao Distribute Data Layer) 技术之前,请允许笔者先吐槽一番。首先要开喷的是淘宝的社区支持做的无比的烂, TaoCode 开源社区上面,几乎从来都是有人提问,无人响应。再者版本迭代速度也同样差强人意 , 就目前而言TDDL 的版本已经全线开源(Group、Atom、Matrix)大家可以在Github上下载源码。

目录

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

二、 TDDL 的架构原型

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

四、 Diamond 简介

五、 Diamond 的安装和使用

六、动态数据源层的 Master/Salve 读写分离 配置与实现

七、 Matrix 层的分库分表配置与实现

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

对于一个刚上线的互联网项目来说,由于前期活跃用户数量并不多,并发量也相对较小,所以此时企业一般都会选择将所有数据存放在 一个数据库 中进行访问操作。但随着后续的市场推广力度不断加强,用户数量和并发量不断上升,这时如果仅靠一个数据库来支撑所有访问压力,几乎是在 自寻死路 。所以一旦到了这个阶段,大部分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 用来存放 diamond server 等地址列表,可以选用任何 http server ,这里以 tomcat 为例。一般来讲, http server 和 diamond server 是部署在不同机器上的,这里简单起见,将二者部署在同一个机器下的同一个 tomcat 的同一个应用中,注意,如果部署在不同的 tomcat 中,端口号一定是 8080 ,不能修改(所以必须部署在不同的机器上)。

在 tomcat 的 webapps 中的 diamond-server 中建立文件 diamond ,文件内容是diamond-server 的地址列表,一行一个地址,地址为 IP ,例如 127.0.0.1 ,完成这些步骤后,就等于已经完成 Diamond 的安装。

六、动态数据源层的 Master/Salve 读写分离 配置与实现

其实使用 TDDL 并不复杂,只要你会使用 JDBC ,那么 TDDL 对于你来说无非就只需要将 JDBC 的操作连接替换为 TDDL 的操作连接,剩余操作一模一样。并且由于TDDL 遵循了 JDBC 规范,所以你完全还可以使用 Spring JDBC 、 Hibernate 等第三方持久层框架进行 ORM 操作。

我们来看看如何 TDDL 中配置 TDDL 的读写分离, Atom+Group 组成了 TDDL 的动态数据源,这 2 层主要负责数据库的读写分离。

TGroupDataSource 的配置

1、   配置读写分离权重:

KEY : com.taobao.tddl.jdbc.group_V2.4.1_ “ groupKey ” (Matrix 中为“ dbKey ” )

VALUE : dbKey:r10w0,dbKey2:r0w10

 

TAtomDataSource 的配置(由 3 部分组成, global 、 app 、 user )

1、   基本数据源信息 (global) :

KEY : com.taobao.tddl.atom.global. “ dbKey ”

VALUE :(

ip= 数据库 IP

port= 数据库端口

dbName= 数据库昵称

dbType= 数据库类型

dbStatus=RW )

 

2、   数据库密码信息 (user) :

KEY : com.taobao.tddl.atom.passwd. “ dbKey ” . “ dbType ” . “ dbUserName ”

VALUE :数据库密码

 

3、   数据库连接信息( app ,如果不配置时间单位,缺省为分钟):

KEY : com.taobao.tddl.atom.app. “ appName ” . “ dbKey ”

VALUE :(

userName= 数据库用户

minPoolSize= 最小连接数

maxPoolSize= 最大连接数

idleTimeout= 连接的最大空闲时间

blockingTimeout= 等待连接的最大时间

checkValidConnectionSQL=select 1

connectionProperties=rewriteBatchedStatements=true&characterEncoding=UTF8&connectTimeout=1000&autoReconnect=true&socketTimeout=12000 )

应用层使用 TDDL 示例:

public class UseTDDL {

    private static final String APPNAME = "tddl_test";

    private static final String GROUP_KEY = "tddltest";

    private static TGroupDataSource tGroupDataSource ;

    /* 初始化动态数据源 */

    static {

        tGroupDataSource = new TGroupDataSource();

        tGroupDataSource .setAppName( APPNAME );

        tGroupDataSource .setDbGroupKey( GROUP_KEY );

        tGroupDataSource .init();

    }

    @Test

    public void testQuery() {

        final String LOAD_USER = "SELECT userName FROM tddl_table WHERE userName=?";

        Connection conn = null ;

        PreparedStatement pstmt = null ;

        ResultSet rs = null ;

        try {

            conn = tGroupDataSource .getConnection();

            pstmt = conn.prepareStatement(LOAD_USER);

            pstmt.setString(1, "tddl-test2");

            rs = pstmt.executeQuery();

            while (rs.next())

                System. out .println("data: " + rs.getString(1));

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            try {

                if ( null != rs)

                    rs.close();

                if ( null != pstmt)

                    pstmt.close();

                if ( null != conn)

                    conn.close();

            } catch (Exception e) {

                e.printStackTrace();

            }

        }

    }

}

 

 

七、 Matrix 层的分库分表配置与实现

       在上一章节中,笔者演示了如何在 Diamond 中配置数据库的读写分离,那么本章笔者则会演示如果配置 TDDL 的分库分表。

       TDDL 的 Matrix 层是建立在动态数据源之上的,所以分库分表的配置和读写分离的基本配置也是一样的,只不过我们需要新添加 dbgroups 和 shardrule 项。 dbgroups项包含了我们所需要配置的所有 AppName 选项,而 shardrule 则是具体的分库分表规则。这里有一点需要提醒各位,在开源版本的 TDDL 中,配置 TGroupDataSource 读写分离是使用 dbKey ,然而在 Matrix 中则是使用 appName 。

1 、配置 Group 组:

KEY : com.taobao.tddl.v1_ “ appName ” _dbgroups

VALUE : appName1 , appName2

2 、配置分库分表规则:

       KEY : com.taobao.tddl.v1_”appName”_shardrule

         VALUE :(

         <?xml version="1.0" encoding="gb2312"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

         <bean id="root" class="com.taobao.tddl.common.config.beans.AppRule" init-method="init">

                   <property name="readwriteRule" ref="readwriteRule" />

         </bean>

    <bean id="readwriteRule" class="com.taobao.tddl.common.config.beans.ShardRule">

                   <property name="dbtype" value="MYSQL" />

                   <property name="tableRules">

                            <map>

                                     <entry key="tddl_table" value-ref="tddl_table" />

                            </map>

                   </property>

         </bean>

         <bean id="tddl_table"   init-method="init"

                   class="com.taobao.tddl.common.config.beans.TableRule">

                   <!-- 数据库组 index 号   -->

         <property name="dbIndexes" value="tddl_test,tddl_test2" />

                   <!-- 分库规则 -->

                   <property name="dbRuleArray" value="(#id#.longValue() % 4).intdiv(2)"/>

                   <!-- 分表规则 , 需要注意的是,因为 taobao 目前 dba 的要求是所有库内的表名必须完全不同,因此这里多加了一个映射的关系

                            简单来说,分表规则只会算表的 key.

                            俩库 4 表 : db1(tab1+tab2) db2(tab3+tab4)

                            db1 == key: 0 value tab1

                                   key: 1 value tab2

                           

                            db2 == key: 0 value tab3

                                   key: 1 value tab4

                   -->

                   <property name="tbRuleArray" value="#id#.longValue() % 4 % 2"/>

                   <property name="tbSuffix" value="throughAllDB:[_0-_3]" />

         </bean>

</beans>

 

         TDDL 的分库分表配置形式完全是采用 Spring 的配置形式,这一点大家应该是非常熟悉的。那么接下来我们一步一步的分析 TDDL 的分库分表规则。

         在元素 <map/> 中我们可以定义我们所需要的分表,也就是说,当有多个表需要实现分表逻辑的时候,我们可以在集合中进行定义。当然我们还需要外部引用<bean/> 标签中定义的具体的表逻辑的分库分表规则。

         在分库分表规则中,我们需要定义 数据库组 index 号,也就是说我们需要定义我们有多少的 appNames ,接下来我们就可以定义分库和分表规则了。 TDDL 的分库分表规则完全是采用取余方式,比如 <property name="dbRuleArray" value="(#id#.longValue() % 4).intdiv(2)"/> , value 属性中包含有具体的分库规则,其中“ #id#”作为我们的分库分表条件,此值在数据库中对应的类型必须是整类,然后进行取余后再进行 intdiv 。或许有些朋友看不太明白这个是什么意思,我们用简单的一点的话来说就是,“ #id#.longValue() % 4).intdiv(2) ”的含义是我们需要分 2 个库和 4 个表,那么我们怎么知道我们的数据到底落盘到哪一个库呢?打个比方,如果我们的 id 等于 10 ,首先 10%4 等于 2 ,然后 2/2 等于 1 , TDDL 分库规则下标从 0 开始,那么我们的数据就是落盘到第 2 个库。

         当大家明白 TDDL 的分库规则后,我们接下来再来分析分表规则 <property name="tbRuleArray" value="#id#.longValue() % 4 % 2"/> 。和分库规则类似的是,我们都采用取余算法首先进行运算,只不过分表尾运算也是使用取余,而不是除算。打个比方,如果我们的 id 等于 10 ,首先 10%4 等于 2 ,然后 2%2 等于 0 ,那么我们的数据就是落盘到第 2 个库的第 1 张表。

 

应用层使用 TDDL 示例:

public class UseTDDL {

    private static final String APPNAME = "tddl_test";

    private static final TDataSource dataSource ;

    /* 初始化动态数据源 */

    static {

        dataSource = new TDataSource();

        dataSource .setAppName( APPNAME );

        dataSource .setUseLocalConfig( false );

        dataSource .setDynamicRule( false );

        dataSource .init();

    }

    @Test

    public void query() {

        final String LOAD_USER = "SELECT userName FROM tddl_table WHERE id = ?";

        Connection conn = null ;

        PreparedStatement pstmt = null ;

        ResultSet rs = null ;

        try {

            conn = dataSource .getConnection();

            pstmt = conn.prepareStatement(LOAD_USER);

            pstmt.setLong(1, 3);

            rs = pstmt.executeQuery();

            while (rs.next())

                System. out .println("data: " + rs.getString(1));

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            try {

                if ( null != rs)

                    rs.close();

                if ( null != pstmt)

                    pstmt.close();

                if ( null != conn)

                    conn.close();

            } catch (Exception e) {

                e.printStackTrace();

            }

        }

    }

    @Test

    public void insert() {

        final String LOAD_USER = "insert into tddl_table values(?, ?)";

        Connection conn = null ;

        PreparedStatement pstmt = null ;

        try {

            conn = dataSource .getConnection();

            pstmt = conn.prepareStatement(LOAD_USER);

            pstmt.setLong(1, 10);

            pstmt.setString(2, "JohnGao");

            pstmt.execute();

            System. out .println("insert success...");

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            try {

                if ( null != pstmt)

                    pstmt.close();

                if ( null != conn)

                    conn.close();

            } catch (Exception e) {

                e.printStackTrace();

            }

        }

    }

}



来源:http://www.tuicool.com/articles/nmeuu2


奇虎360公司开源的Atlas是优秀的数据库中间件,美团点评DBA团队针对公司内部需求,在其上做了很多改进工作,形成了新的高可靠、高可用企业级数据库中间件DBProxy,已在公司内部生产环境广泛使用,较为成熟、稳定。 DBProxy的优点 支持多语言MySQL客户端 读写分离 负载均衡 Slave故障感知与摘除(Master需要MHA等其他联动) 后端连接池 自定义SQL拦截与过滤 流量分组与控制 丰富的监控状态 支持分表(分库版本正在内测中) Client IP限制 DBProxy对Atlas的改进 新增功能点 新增参数 backend-max-thread-running用于指定每个MySQL后台的最大thread running数 thread-running-sleep-delay用于指定在thread running数超过backend-max-thread-running时,客户端连接等待的时间 添加到黑名单中需要满足两个条件:SQL执行的时间和频率 提供了查看、修改、添加、删除黑名单的功能 黑名单管理提供了将黑名单保存到文件以及从文件中Load到内存中的功能 在手动添加黑名单时,只需要将用户的SQL语句输入,在内部自动化成过滤条件,手动添加时是否生效由参数 manual-filter-flag 来控制,OFF:不生效,ON:立即生效 手动添加与自动添加两种情况下的过滤条件是否生效是分别由不同参数控制,这个要区分清楚。另外,也可以使用 admin 的命令来设置是否开启/关闭某个过滤条件 SQL执行的时间 由参数 query-filter-time-threshold 来指定,如果SQL执行时间超过此值,则满足条件 SQL执行频率 由参数 query-filter-frequent-threshold 来指定,如果SQL执行频率超过此值,则满足条件 频率就是在时间窗口内执行的次数。时间窗口则是由频率阈值和最小执行次数来计算出来的,当时间窗口小于60s时,扩展到60s 参数 access-num-per-time-window 用来指定在时间窗口内的最小执行次数,添加此参数是考虑到执行时间长的SQL在计算频率时同时参考其执行的次数,只有执行一定次数时才去计算其频率。当执行时间与执行频率都满足时条件时,会自动将查询作为过滤项放到黑名单中,加入到黑名单中是否生效由参数 auto-filter-flag 来控制,OFF:不生效,ON:立即生效 黑名单的管理 从库流量配置 指定查询发送到某个从库 参数动态设置(完善show proxy status/variables) 支持save config,动态增加、删除分表 响应时间percentile统计 统计最近时间段DBProxy的响应时间 kill session 支持DBProxy的admin接口kill session操作 backend平滑上下线 支持平滑的backend上下线 DBProxy非root用户启动 使用非root用户启动 admin账号的安全限制 admin账号密码的动态修改及host限制 增加异步刷日志的功能 增加日志线程、异步刷日志,提高响应时间 支持DBProxy平滑重启功能 支持SQL过滤的黑名单功能 支持对于MySQL后台的thread running限制功能 该功能通过在DBProxy内限制每个后台MySQL的并发查询,来控制对应MySQL的thread running数 当发向某个MySQL后台的的并发查询超过某个阈值时,会进行超时等待,直到有可用的连接,其中阈值与超时等待的时间都已经参数化,可以动态配置 set backend offline不再显示节点状态 支持set transaction isolation level 支持use db 支持set option语句 支持set session级系统变量 支持建立连接时指定连接属性 改进连接池的连接管理,增加超时释放机制。当连接池中的空闲连接闲置超过一定时
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值