zdal配置文件_Zdal分库分表介绍、超详细一步一步搭建简单的zdal框架

Zdal分库分表、超详细一步一步实现使用zdal搭建框架

转载请标明出处,谢谢~!^^,有问题一起讨论 _______by-陶浩伟

背景:

我在的开发小组比较空闲,在看完业务逻辑后,暂时没什么任务的我研究起了小组项目的搭建。

小组项目是一个分布式项目,逻辑比较简单,但是用到的技术比较全面。分别用到 dubbo分布式服务框架、MQ消息队列、redis、Zdal分库分表、Mybatis、spring等

技术在业务逻辑上的体现大致为:

正文

1、什么是zdal? 它能解决什么问题?

2、zdal的组成

3、搭建的项目展示

4、zdal搭建所需环境

5、zdal配置文件的配置

6、编写测试类,测试项目搭建

7、异常处理建议

1、什么是zdal? 它能解决什么问题?

注:本文参照了些该文(同后)的内容,加上自己的理解,侧重实际搭建,内容有表述不清楚的地方,请参照文档理解–作者:黄磊,若有错误知错,请大家指出^^。

1.1 什么是zdal?

Zdal是支付宝自主研发的数据中间件产品,采用标准的JDBC规范,可以在分布式环境下看上去像传统数据库一样提供海量数据服务,是一种通用的分库分表数据库访问框架。

1.2 它能解决什么问题?

它能在数据访问压力过大时,解决单库单表数据库访问压力,Zdal主要提供分库分表,分散压力,结果集合并,sql解析,数据库failover动态切换等功能,提供互联网金融行业的数据访问层统一解决方案,

1.3 实际运用

目前已经在支付宝的交易,支付,会员,金融等大部分关键应用上使用,并且在2013年双11大促中运行稳定。

2、zdal的组成、zdal是怎么实现的?

2.1 zdal组件主要有5部分组成:

Zdal-client:开发编程接口,实现jdbc的Datasource,Connection,Statement,PreparedStatement,ResultSet等接口,实现通用的jdbc-sql访问,内部还实现读库重试,group数据源的选择器,表名替换,sql执行器等功能。

Zdal-parser:支持oracle/mysql/db2等数据库的sql语句解析,并且缓存。根据规则引擎提供的参数列表,在指定的sql中查找到需要的参数,然后返回拆分字段。

Zdal-rule:根据zdal-parser解析后的拆分字段值来确定逻辑库和物理表名。

Zdal-datasource:数据库连接的管理,支持mysql,oracle,db2数据库的连接管理。

Zdal-common:zdal组件所使用的一些公共组件类

2.3 zdal是怎么实现的呢?

a、不同于以往的jdbc连接,zdal实现同时与多个数据源绑定

b、根据规则引擎生成的目标库id和表名,根据其中的某个字段计算该数据属于的物理数据库

c、然后动态指定读库,对该库进行操作

3、搭建的项目展示

3.1 项目介绍

项目一共使用两个数据库服务器,分别是本机和远程的数据库服务器,共分了4个数据库DB,平均分布共12张城市信息表,每个数据库中3张城市信息表,城市信息表中只有两个字段,分别是id和cityName.

数据库DB命名规则为test_XX(索引),城市信息表命名规则为t_city_XX(索引)

3.2 数据库目录结构、以及表展示

//表的创建sql语句

CREATE TABLE test_00.t_city_00 (

`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增ID',

`cityName` varchar(32) NOT NULL COMMENT '城市名',

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;`

3.3 项目目录结构展示

4、zdal搭建所需环境

1、zdal需要本身自己的jar包,可以点击下载,百度云密码:9e9x。

2、需要spring相关jar包

3、需要jdbc-driver-mysql的jar包

4、项目中使用了mybatis、所以还需要mybatis相关jar包。

5、如有需要可引入log相关jar包

使用时可以下载zdal包后,解压到maven的仓库中,然后如下配置

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

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

test1

zdal_test

1.0-SNAPSHOT

1.0-SNAPSHOT

3.2.9.RELEASE

4.10

1.2.0

1.0

com.alipay.zdal

zdal-client

${zdal.version}

org.springframework

spring

junit

junit

${junit_version}

test

org.mybatis

mybatis

3.3.0

org.mybatis

mybatis-spring

${mybatis-spring_version}

mysql

mysql-connector-java

5.1.36

org.springframework

spring-core

${spring_version}

org.springframework

spring-beans

${spring_version}

org.springframework

spring-context

${spring_version}

org.springframework

spring-jdbc

${spring_version}

5、zdal配置文件的配置

5.1 完成zdal-rule类

zdal-rule主要是完成规则的计算,包括分库的计算和分表的计算,相当于是一个二次路由的过程,这里使用在代码里封装拆分规则静态方法,在规则里调用该静态方法。

通俗的说,就是为了zdal判断,这条数据是存在哪个数据库服务器,哪个数据库的哪个数据表

这里我写的计算过程很简单,就是根据城市id来计算的,代码如下:

package com.util;

/**

* Created by Administrator on 2017/7/20.

*/

public class ZdalRuleParser {

/**

* 解析得到分库的数据库

*@param id

*@return

*/

public static int parserDbIndex(int id) {

//因为一共四个库,直接对4取余即可取到所有的数据库(0,1,2,3)

return id%4;

}

/**

* 解析得到分表的表结构

*@param id

*@return

*/

public static int parserTbIndex(int id) {

int index = parserDbIndex(id);

//{(0-0,1,2),(1-3,4,5),(2-6,7,8)}-索引为0的数据库对应0,1,2三张表、索引为1的数据库对应3,4,5三张表

//这里根据数据库索引,乘3+id对3取余,即可对得到对应的表

//例如,id为3时,数据库索引为3,表索引为9.则这条数据插入在test_03中的t_city_09中

int tbIndex = index*3+id%3;

return tbIndex;

}

}

5.2 完成zdal-rule配置文件

这里的配置规则可以参考1中的文档理解,里面对每条property属性含义有比较全面的解释。

—图片转自文档理解—

—图片转自文档理解—

这个配置文件对应 3.3 项目目录结构展示 中的/resource/config/zdal-dev-rule.xml文件,主要实现内容是关联上述5.1中的配置类,分别对应数据库、表的计算,代码如下

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

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

return com.util.ZdalRuleParser.parserDbIndex(#id#);

return com.util.ZdalRuleParser.parserTbIndex(#id#);

5.3 完成zdal-ds数据源配置文件

这里的配置规则可以参考1中的文档理解,里面对每条property属性含义有比较全面的解释。

—图片转自文档理解—

—图片转自文档理解—

这个配置文件对应 3.3 项目目录结构展示 中的/resource/config/zdal-dev-ds.xml文件,主要实现是关联zdal-dev-rule.xml文件。将数据库源连接,这里需要注意的几点有:

a、两个配置文件的名称,需要与ZdalAppBean中的appName、dbmode相关联,格式为 appName-dbmode-ds/rule.xml 如果名称不按格式来,zdal初始化时会加载不成功。

b、配置数据源时(也就是PhysicalDataSourceBean),多个数据库服务器需要配置多个对应数据库连接源,然后在(AppDataSourceBean)中绑定,形成一对多的数据库结构。具体参考如下代码:

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

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

5.4 完成城市相关逻辑,以及mapper配置文件

接下来就很简单,城市相关逻辑很简单,逻辑只实现包含一条向数据库中插入一条城市信息。{(id,1),(cityName,北京)},直接看代码就可以好。如下:

//biz包--即CityService,具体所处位置可参考3.3项目目录结构图

@Service

public class CityService {

@Autowired

private CityMapper cityMapper;

public void insert(City city)

{

System.out.println("开始插入");

int i = cityMapper.insertCity(city);

System.out.println("插入结果为:"+i);

}

}

//mapper包--即CityMapper接口,接口位置请参考3.3项目结构目录

public interface CityMapper {

public int insertCity(City city);

}

//对应/resources/mapper/cityMapper.xml配置文件

INSERT INTO t_city (id,cityName) VALUES (#{id},#{cityName})

//model包--City模型

public class City {

private int id;

private String cityName;

//........省略构造方法........

//........省略getter和setter........

}

5.5 完成spring配置文件

spring配置文件也很简单,只需要配置zdal分库分表的数据源,将mybatis数据源与其绑定即可。

注意:这里的dbmode、appname和appDsName与zdal-dev-ds中的相对应

代码实现如下:

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

xmlns:context="http://www.springframework.org/schema/context"

xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd

http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">

6、编写测试类,测试项目搭建

至此,配置相关的内容结束、实际操作也很方便,重点在zdal对我们熟悉的dao层编程几乎没有任何入侵,只需要在对数据库操作前,查询库的路由规则(咱们在ZdalRuleParser类中自己写的那个实现类),得到实际操作的数据。

内容步骤如下:

1、初始化spring容器,得到数据库对应的数据源

2、从数据源中得到 逻辑物理数据源名称(logicPhysicsDsNames),用于初始化logicPhysicsIndexes数据源集合

3、开始执行插入操作,通过在ZdalRuleParser类写的映射规则,使用递增id计算得到这条数据分库分表的索引。(例如id=3,分库对应test_03,分表对应t_city_09)

4、将计算得到的分表组成数据库表示路由条件,然后将这个对象添加到线程中。(这两步想当于告诉接下来数据库插入的操作,你要往分库对应test_03,分表对应t_city_09这个数据源中插入数据,别插错了。)

5、执行插入操作

import com.alipay.zdal.client.ThreadLocalString;

import com.alipay.zdal.client.jdbc.ZdalDataSource;

import com.alipay.zdal.client.util.ThreadLocalMap;

import com.alipay.zdal.client.util.condition.DBSelectorIDRouteCondition;

import com.biz.CityService;

import com.model.City;

import com.util.ZdalRuleParser;

import org.junit.Before;

import org.junit.Test;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.text.DecimalFormat;

import java.util.HashMap;

import java.util.Map;

/**

* Created by Administrator on 2017/7/20.

*/

public class MyTest {

private CityService service;

private ZdalDataSource dataSource;

// 所有配置的物理数据源, dbIndex

private Map logicPhysicsIndexes;

//库名

private String dbName = "test";

//表名

private String tbName = "t_city";

@Before

public void init()

{

//加载spring容器,实例化bean

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");

service = (CityService) context.getBean("cityService");

dataSource = (ZdalDataSource) context.getBean("dataSource");

//实例化逻辑数据源

logicPhysicsIndexes = new HashMap();

//得到物理数据源名称

Map logicPhysicsDsNames = dataSource.getZdalConfig().getLogicPhysicsDsNames();

//将其存入物理数据源数据 {(0,master_00),(1,master_01)...}

for (String name : logicPhysicsDsNames.keySet()) {

String[] split = name.split("_");

logicPhysicsIndexes.put(Integer.valueOf(split[1]), name);

}

}

@Test

/**

* 插入数据库操作

*/

public void insert(){

//设置插入10条id数据,id自增

for (int id=30;id<40;id++) {

// 指定查詢库的路由規則

//根据规则得到分库索引

int dbIndex = ZdalRuleParser.parserDbIndex(id);

String dbSelectorID = logicPhysicsIndexes.get(dbIndex);

System.out.println("dbSelectorID = " + dbSelectorID);

//根据规则得到分表索引

int tbIndex = ZdalRuleParser.parserTbIndex(id);

String tablePostfix = new DecimalFormat("_00").format(tbIndex);//如果tbIndex为3,tablePostfix为_03

//根据分表索引得到物理表名称

String physicTableName = tbName + tablePostfix;

System.out.println("physicTableName = " + physicTableName);//physicTableName = t_city_00、t_city_01、t_city_02等

//得到 数据库选择器标识路由条件---确定是存在哪一个数据库中

DBSelectorIDRouteCondition dbSelectorIDRouteCondition = new DBSelectorIDRouteCondition(

"t_city", dbSelectorID, physicTableName);

//将分库分表添加到线程中

ThreadLocalMap.put(ThreadLocalString.ROUTE_CONDITION, dbSelectorIDRouteCondition);

System.out.println("配置完成,准备开始插入数据");

City city = new City(id, "北京");

service.insert(city);

}

}

}

运行结果:

Run输出台:

数据库数据:

7、异常处理建议

配置过程中,不要错漏掉某些数据,在运行测试类时,如果碰上异常,耐心的看它报的错误指向,观察zdal的源码,观察它在出错的那一段是想要做什么事情,抛出的异常,然后根据这个逻辑,去寻找到底是哪一块出错,耐心一些^^

结束

转载请标明出处,谢谢~!^^,有问题一起讨论 _______by-陶浩伟

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值