原文地址:https://zhuanlan.zhihu.com/p/25166375
DDAL在设计上主要可以分为三层:
基于上图架构的一个完整的工程示例:
hellojavaer/ddal另一个简单的读写分离的工程示例
hellojavaer/ddal
2.绑定路由规则到逻辑表名或逻辑库(逻辑schema)上,并设置分片字段(也可以不设置分片字段)
通过这个绑定,可以计算出一个逻辑表名对应的物理表名和一个逻辑库(schema)对应的为物理库(schema)
3. 解析并重写sql
DDAL支持的sql主语法有select,insert,delete,update,支持主语法下的几乎所有sql子语法,包括sub-select,union,exsit, join等
解析sql的过程就是识别sql中的所有表名,如果某一个表名能匹配到步骤2中的逻辑表名,则该表名会根据步骤1中规则进行表名重写,如果没匹配到则不做任何操作,同时所有被重写后的表名会被放在一个结果集用于步骤4数据源的获取。
在重写sql时一个关键的点是获取路由信息,DDAL对分表路由信息的获取分为两大类:
(1)通过sql中的分片值
(2)通过ShardRouteContext;
其中方式(1)优先于方式(2),只有当方式(1)获取失败后才会尝试从方式(2)中获取。而如果两种方式都不能获取到路由信息则会抛出异常,比如:
select * from tb where id = 9
上面的tb匹配了步骤2的绑定,因此会执行表名重写;而id字段又匹配了分片字段,因此会执行方式(1)的分片值重写,重写后的结果为
SELECT * FROM base_01.tb_0001 WHERE id = 9
而如果当sql中不含分片字段或分片字段不能计算路由信息时(比如: id != 9)
select * from tb where WHERE name = 'test'
这时可以通过ShardRouteContext设置路由信息
ShardRouteContext.setRouteInfo('base', 9);
重新后的sql为
SELECT * FROM base_01.tb_0001 WHERE name = 'test'
同时DDAL为了简化ShardRouteContext的调用,提供ShardRoute注解进行配置,注解的配置和ShardRouteContext是完全等效的,因为ShardRoute底层使用的就是ShardRouteContext,例如:
// 当id的值为9时,路由结果的信息完全等同于 ShardRouteContext.setRouteInfo('base', 9);
@ShardRoute(scName = "base", sdValue = "{$0}")
public void test(Long id){}
4.选取数据源并执行
这一步的核心是数据源管理器,它通过将步骤3中计算出的物理库的结果集用于筛选出实际的数据源去执行。而DDAL目前的数据源管理器包含两个:SingleDataSourceManager和DefaultReadWriteDataSourceManager。
SingleDataSourceManager不依赖步骤3计算的物理库结果集,因为它内部只管理了一个数据源,所以不论步骤3返回什么结果集,SingleDataSourceManager都只会把它管理的那一个数据源返回用于sql的执行;
DefaultReadWriteDataSourceManager实现了一个读写分离的数据源管理器,读和写都可以配置多个数据源,读数据源支持配置负载权重。由于内部包含多个数据源因此步骤3的物理库结果集必须至少包含一个结果,用于匹配实际的数据源(如果未匹配中则会抛出异常)
以上完整的配置信息参考以下链接
https://github.com/hellojavaer/ddal/blob/master/ddal-example/ddal-example-example0/src/main/resources/datasource.xmlDDAL的设计方向完整的保留数据库ACID的所有特性,在一个数据源连接下的跨schema和跨table操作是允许的(因为底层数据库是支持的);当出现跨连接操作时,DDAL设计方案是将跨连接的数据进行分组使得分组后的每组数据都在一个连接内。在DDAL中提供的一个实现类是ShardRouteUtils,你可以先使用groupSdValuesByRouteInfo对shard-value进行分组,然后使用groupRouteInfosByDataSource对关联的数据源进行分组。分组后的shard-value再进行操作时每一组的操作就都能完整的保证ACID,不同分组间的操作异常由业务自行进行控制;
参考以下链接
hellojavaer:ddal-sequence设计方案