Spring+iBatis 的多库横向切分简易解决思路(4)

2019-04-21 19:34

class=\ FailoverHotSwapDataSourceCreator将定时的发送该SQL到目标数据库, 对目标数据库的状态进行探测, 如果超时或者抛出异常, 那么重试指定次数之后依然如此的话, FailoverHotSwapDataSourceCreator会将目标数据库热切换到备用目标数据库上去. 探测的时间间隔, 探测的超市时间, 探测的重试次数等, 都可以通过相应的属性进行设置, 更多这方面的信息可以参考FailoverHotSwapDataSourceCreator的javadoc文档.

5.2.2. 数据访问请求路由(Routing In CobarSqlMapClientTemplate)

除了依赖某个ICobarDataSourceService进行多数据源的管理, CobarSqlMapClientTemplate的另一个主要依赖就是ICobarRouter, ICobarRouter负责将相应的数据访问请求路由到指定的数据源上去.

5.2.2.1. Router Design

ICobarRouter抽象接口定义如下:

public interface ICobarRouter { RoutingResult doRoute(T routingFact) throws RoutingException; } 该接口将根据指定的路由上下文信息(routingFact)返回最终的路由结果.

我们可以根据情况提供不同的ICobarRouter实现类, 比如Cobar Client默认提供的com.alibaba.cobar.client.router.CobarClientInternalRouter和

om.alibaba.cobar.client.router.DefaultCobarClientInternalRouter, 或者如果路由规则数量很多, 为了保证性能, 也可以实现基于Rete等算法的实现类等. 没有特殊需求的情况下,我们默认采用CobarClientInternalRouter作为CobarSqlMapClientTemplate使用的默认Router实现. 但用户也可以根据情况选用DefaultCobarClientInternalRouter, 二者的使用是类似的。

DefaultCobarClientInternalRouter在CobarClientInternalRouter的基础上, 对路由规则的匹配进行了分组优化, 通过配置时期的复杂度换取运行时期的简单高效。 如果规则很多的话,可以考虑使用DefaultCobarClientInternalRouter。 Note

DefaultCobarClientInternalRouter的配置可以通过两个专门的FactoryBean进行, 即 com.alibaba.cobar.client.router.config.DefaultCobarClientInternalRouterXmlFactoryBean 和 com.alibaba.cobar.client.router.config.StaticCobarClientInternalRouterFactoryBean, 前者允许用户通过外部XML的配置文件形式来定义和加载路由规则, 后者运行用户直接在Spring的IoC容器中以bean定义的形式定义路由规则。 应用方可以根据情况选用。详细使用情况可以参考相应类的javadoc以及下面有关CobarClientInternalRouter的使用和配置信息。

因为CobarSqlMapClientTemplate主要面向iBatis, 所以, 它使用的CobarClientInternalRouter接受的路由上下文信息(routingFact)类型为IBatisRoutingFact:

public class IBatisRoutingFact { // SQL identity private String action; // the argument of SQL action private Object argument; // ... } 也就是说, CobarClientInternalRouter将根据两部分信息进行路由, 一就是sqlmap中的sqlmap id, 另一个就是传入的数据访问方法参数. CobarClientInternalRouter将根据一组或则多组路由规则对传入的IBatisRoutingFact类型的路由上下文信息进行匹配, 将匹配的结果返回, 之后, CobarClientInternalRouter就可以根据匹配的结果来决定最终的数据访问操作将在哪些数据源上执行了.

5.2.2.1.1. CobarClientInternalRouter的配置(Configuration of CobarClientInternalRouter)

默认情况下, CobarClientInternalRouter将接收4组不同类型的路由规则, 但路由规则的类型对于用户来说实际上是不必要的, 所以, 为了避免用户过多的纠缠于

CobarClientInternalRouter的实现细节, 我们给出了针对CobarClientInternalRouter配置的一个Spring的FactoryBean实现, 以帮助简化CobarClientInternalRouter的配置, 该FactoryBean实现类为com.alibaba.cobar.client.router.config.CobarInteralRouterXmlFactoryBean, 其一般的配置方式如下:

CobarInteralRouterXmlFactoryBean将根据指定的xml形式的配置文件中的内容, 自动构建不同类型的路由规则, 然后注入到它将最终返回的

CobarClientInternalRouter实例之上. 而读取, 解析配置信息, 并构建不同类型路由规则等 “琐事 ” 将完全对用户透明.不过, 再怎么屏蔽, 有得事情还是需要用户提供的, 比如配置文件的内容, 用户必须按照应用程序的部署情况提供正确地路由规则定义,

CobarClientInternalRouter才会正确的工作.所以, 下面我们将详细介绍路由规则的相关信息. Tip

除了可以通过configLocation属性指定单一的配置文件路径, 也可以通过configLocations指定多个配置文件路径,这通常有助于模块化并行开发. Note

虽然默认情况下我们推荐使用CobarInteralRouterXmlFactoryBean进行

CobarClientInternalRouter的配置, 但我们同样可以给出基于DSL甚至Excel等形式路由规则

定义对应的FactoryBean.只要应用需要, 这些都是可以在现有的基础上进行扩展的.

5.2.2.2. 路由规则详解(Rules In Details)

5.2.2.2.1. 路由规则定义格式(Rule Definitions)

一个最简单的路由规则定义文件内容可以如下所示:

下包含多个元素, 而下又包含4个子元素:

namespace 或者 sqlmap. 属于路由规则条件的一部分, 二者的唯一区别在于指定的条件明确程度不同, sqlmap直接对应每一个iBatis的SqlMap文件中某个statement的定义的id,而namespace则对应每一个iBatis的SqlMap文件中定义的namespace. 这两个元素在元素下只能取其一.否则在通过CobarInteralRouterXmlFactoryBean进行配置的时候, 将抛出配置相关异常.

shardingExpression. 遵循MVEL形式的表达式定义, 同样属于路由规则条件的一部分, 主要对数据访问请求的参数进行匹配, 属于动态条件, 通常用于横向切分规则的定义.

shards. 路由规则结果部分, 如果以上多个路由规则条件匹配成功, 则返回该元素的值作为路由结果.

以上rule定义简单来说表达了condition->action的语义, 即具体化为(namespace | sqlamp) + shardingExpression -> shards.

以上规则定义其实很简单,所以并不强制使用DTD或者XML Schema等来验证文档的合法性, 如果需要, 可以参考如下的DTD定义:

那么, 以上元素到底应该如何根据应用程序的情况进行定义那? 让我们接着来看下一节的 “路由规则类型详解 ” 吧! Note

CobarClient使用MVEL对shardingExpression进行求值, 所以, 起草的shardingExpression只要符合MVEL的语法就可以。有关MVEL的语法, 可以参考MVEL的 官方文档 。

5.2.2.2.2. 路由规则类型详解(Rule Types Explained)

路由规则的定义初看起来简单, 但到底应该如何定义, 以及为什么要如此定义, 在没有为你揭开这些疑问之前,我想, 你还是很难搞清楚这些路由规则定义到底是怎么回事, 不过没关系, 我们现在就为你揭开这些疑团.

在使用iBatis进行数据访问的时候,我们通常会定义相关的SqlMap文件, 例如:

... 其中, 每个SqlMap都会对应一个namesapce, 在该namespace下, 可以定义多个sql statement, 而每个statement又会有相应的id作为其标志, 其中, namespace + id可以唯一标志一个全局的sql statement, 在这一前提下, 让我们来看如何根据现有iBatis的SqlMap的定义来进行数据访问的路由.

我们本着从特殊到一般的情况进行推演.

以create操作为例, 假设我们的offer数据现在分布在两台数据库上, 而根据切分规则,

memberId为奇数的数据分布在数据库1上, memberId为偶数的数据分布在数据库2上, 在这一前提下, 要路由offer的创建相关的数据请求, 最明了的方式就是, 检查当前数据访问对应的sql statement是哪个, 并判断传入的参数包含的memberId是奇数还是偶数, 这样, 我们就有了以下2个路由规则定义:

com.alibaba.cobar.client.entities.Offer.create memberId % 2 == 1 partition1

com.alibaba.cobar.client.entities.Offer.create memberId % 2 == 0 partition2 元素对应唯一的sql statement标志, 即namespace + sql statement id, 对应切分规则的定义, 而则对应最终的路由结果. 现在, 我想你应该对路由规则的如上定义有了初步的了解了吧!

有了以上的基础, 我们来变换假设场景, 我们依然是create操作, 但现在我们不是做的水平切分, 而只是做垂直切分, 也就是说, 所有的offer数据现在假设都会落在同一台数据库上, 那么, 以上的定义可以变更为:

com.alibaba.cobar.client.entities.Offer.create memberId % 2 == 1 partition1

com.alibaba.cobar.client.entities.Offer.create memberId % 2 == 0 partition1 即不管切分规则如何, 他们的合集都是落在partition1上, 可是, 如果真的这么定义的话, 那看起来是不是有些stupid那? 答案肯定是yes, 所以, 对应这种情况, 我们的路由规则可以定义如下:


Spring+iBatis 的多库横向切分简易解决思路(4).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:复变函数与积分变换试题1

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: