Spring+iBatis 的多库横向切分简易解决思路
更新时间:2024-05-29 15:09:01 阅读量: 综合文库 文档下载
Spring + iBatis 的多库横向切分简易解决思路
I. 向Cobar Client迁移
1. Cobar Client使用迁移手册(Cobar Client Migration Guide) 1.1. 数据分区多数据源的依赖管理说明
1.2. CobarSqlMapClientTemplate其它相关配置说明 1.2.1. 数据访问路由相关配置 1.2.2. What's Next?
II. Cobar Client百科大全 2. CobarClient发起的背景 3. CobarClient最初需求
4. CobarClient方案之间的权衡 4.1. JDBC API层次的解决方案 4.2. DAL层次的解决方案
4.3. 特定国际站场景的解决方案
5. Cobar Client参考文档(Cobar Client Reference Documentation) 5.1. 鸟瞰Cobar Client现有架构实现 5.2. CobarSqlMapClientTemplate详解
5.2.1. 多数据源依赖管理(Multiple DataSources Management)
5.2.2. 数据访问请求路由(Routing In CobarSqlMapClientTemplate) 5.2.3. SqlAuditing
5.2.4. 其它配置与特性解释(Other Configuration or Features Explained) 5.3. MultipleDataSourcesTransactionManager详解
5.3.1. MultipleDataSourcesTransactionManager依赖的多数据源管理 6. CobarClient展望
Part I. 向Cobar Client迁移
Chapter 1. Cobar Client使用迁移手册(Cobar Client Migration Guide) 1.1. 数据分区多数据源的依赖管理说明
1.2. CobarSqlMapClientTemplate其它相关配置说明 1.2.1. 数据访问路由相关配置 1.2.2. What's Next?
CobarClient主要针对现有网站应用中使用iBatis做数据访问层这一情况而设计开发,如果你的应用程序最初使用了Spring提供的SqlMapClientTemplate的话, 那迁移到CobarClient实际上仅仅是稍微改一下应用程序的配置而已.
假设原有的应用程序依赖于Spring的SqlMapClientTemplate进行数据访问, 那么, 使用Cobar Client之后, 只要修改配置, 让应用程序依赖于CobarClient的
CobarSqlMapClientTemplate即可. 同时, 与数据访问相关的事务管理也需要从使用Spring原生的DataSourceTransactionManager, 换为CobarClient提供的
MultipleDataSourcesTransactionManager, 整个迁移的概况类似于:
使用CobarClient之前:
class=\ class=\ 使用CobarClient之后: class=\ class=\ ... 不过, 以上只是简化后的迁移场景, 实际上, 还有一些细节需要我们完善之后, 才能完全的完成整个的迁移工作. 1.1. 数据分区多数据源的依赖管理说明 在单数据源的情况下, SqlMapClientTemplate(或者说它依赖的SqlMapClient)以及对应进行事务管理的 DataSourceTransactionManager都会引用同一个数据源; 而当应用进行数据拆分之后, 物理上将对应多个数据源, 要进行数据访问和事务管理, 我们现在必须针对数据拆分之后对应的多个数据源进行.为了同一的管理这种依赖, CobarClient提供了 ICobarDataSourceService这一抽象接口用于归类管理数据拆分后对应的多个数据源, com.alibaba.cobar.client.CobarSqlMapClientTemplate和 com.alibaba.cobar.client.transaction.MultipleDataSourcesTransactionManager 现在将都依赖于某个ICobarDataSourceService的实现来提供对某些数据源的依赖, 这样, 最初的配置将演化为如下的形式: class=\ CobarSqlMapClientTemplate都有一个cobarDataSourceService 依赖, 该依赖都将引用同一个bean定义dataSources (注意这里的名称为复数). 该bean定义将对应某个ICobarDataSourceService实现类, 当前, 我们提供了 com.alibaba.cobar.client.datasources.DefaultCobarDataSourceService作为ICobarDataSourceService的默认实现, 其常见配置如下: class=\ class=\ value=\ value=\/> value=\ value=\/> com.alibaba.cobar.client.datasources.CobarDataSourceDescriptor, 每一个 com.alibaba.cobar.client.datasources.CobarDataSourceDescriptor 描述了针对某一数据拆分分区的必要依赖, 这包括: identity. 数据分区的唯一标志, 该标志不可与其它数据分区的标志冲突, 在定义路由规则的时候, 数据分区标志将成为路由规则的一部分. targetDataSource. 主要目标数据源的依赖引用, 通常意义上, 应用启动的时候该数据源必须是Active的. targetDetectorDataSource. 主要目标数据源伴随的HA探测用数据源, 主要用于检测主要目标数据源的状态, 通常指向与主要目标数据源相同的目标数据库, 但数据库连接池要单独配置, 以防止相互干扰. standbyDataSource. 与主要目标数据源并列的备用数据源, 当主要目标数据源出现问题之后, 如果启用了CobarClient的HA功能支持, CobarClient将自动将数据访问切换到该备用数据源上. standbyDetectorDataSource. 备用数据源对应的HA探测用数据源. Note 因为当前网站的数据源配置都是通过JNDI进行, CobarClient无法统一取得数据库连接等相关信息, 也就无法根据同一份配置信息自行创建相应的数据库连接池, 所以, 只好需要应用程序方针对每一个目标数据源再多配置一个用于HA状态探测用的数据源引用. 当前CobarDataSourceDescriptor之所以需要这些信息是因为现在网站最主要的数据库部署 结构是HA双机热备的水平切分数据库集群, 但后期如果有其它的数据库部署结构, CobarDataSourceDescriptor也可能随着数据库部署结构的调整而调整. Tip 如果不需要HA双机热备支持, 那么可以让standby(.*)DataSource指向target(.*)DataSource相同的数据源应用, 或者如果DefaultCobarDataSourceService的haDataSourceCreator没有指定的话, standbyDataSource,standbyDetectorDataSource和targetDetectorDataSource可以完全不配置. CobarDataSourceDescriptor引用的数据源可以来自JNDI绑定的数据源, 也可以来自容器内定义的数据源(如上配置所示, 为了测试,我们使用了Spring容器内定义的C3P0数据源), 甚至其它形式提供的数据源, 只要为其提供标准的JDBC API中的DataSource接口实现即可. DefaultCobarDataSourceService除了依赖一组CobarDataSourceDescriptor, 它还依赖于相应的IHADataSourceCreator来进行数据库的HA支持, 如果没有提供相应的IHADataSourceCreator实现类, DefaultCobarDataSourceService默认会使用 NonHADataSourceCreator, 即不创建支持HA的数据源. CobarClient默认提供了FailoverHotSwapDataSourceCreator以支持HA, 应用方可以根据情况提供自己的IHADataSourceCreator实现来满足特定场景需要. 有关数据切分分区多数据源管理相关的迁移说明就说到这里, 下面我们来进一步看一下其它相关配置细节. 1.2. CobarSqlMapClientTemplate其它相关配置说明 因为 com.alibaba.cobar.client.transaction.MultipleDataSourcesTransactionManager 属于标准的Spring的PlatformTransactionManager实现, 除了唯一特定于CobarClient的ICobarDataSourceService依赖之外, 其它都继承自Spring标准类 AbstractPlatformTransactionManager, 故此其配置在这里就不做更多说明了,应用方可以参阅Spring的相关文档获取更多配置和使用信息. 下面我们主要针对CobarSqlMapClientTemplate的相关依赖进行进一步说明. 1.2.1. 数据访问路由相关配置 CobarSqlMapClientTemplate依赖某个ICobarDataSourceService实现类来获取数据拆分分区相关信息, 为了将相应的数据访问请求路由到相应的数据分区, 它也需要依赖于一个ICobarRouter实现类以决定如何进行数据访问请求的路由. 所以, 一个功能完备的CobarSqlMapClientTemplate配置应该如下所示: class=\ 关于sqlAuditor, profileLongTimeRunningSql, longTimeRunningSqlIntervalThreshold等配置项, 可以参考CobarClient Reference文档, 他们是可选的, 所以这里不做更多说明. Cobar Client默认提供的ICobarRouter实现类是 com.alibaba.cobar.client.router.CobarClientInternalRouter, 为了简化配置, 我们为其提供了一个FactoryBean用于简化配置, 即 com.alibaba.cobar.client.router.config.CobarInteralRouterXmlFactoryBean, 其中最主要的配置项为configLocations(或者configLocation, 如果只需要指定一个路由规则说明文件的话), 该配置项主要用于指定路由规则说明文件所在的位置, com.alibaba.cobar.client.router.CobarClientInternalRouter将根据这些路由规则说明文件中的路由规则进行数据访问请求的路由. 下面是一个典型的路由规则说明文件实例: com.alibaba.cobar.client.router.config.CobarInteralRouterXmlFactoryBean的时候,我们通过functionsMap属性指定了一个自定义函数Map的话, 那么,在路由规则的shardingExpression中, 就不难发现该自定义函数的身影了. 因为以上路由规则定义很简单,所以我们没有强制要求使用DTD或者XML Schema,但实际上, 路由规则的DTD可以简单描述如下: 路由规则在当前的CobarClient中分为四种类型, 详情参见CobarClient Reference文档. 总之, 有了以上配置之后, 你就可以开始使用Cobar Client进行数据切分集群下的数据访问之旅了. 1.2.2. What's Next? 迁移文档只是简单说明了使用CobarClient需要做的最基本工作, 但过多细节不会涉及, 比如路由规则的详细定义如何进行, HA如何配置等等, 要了解这些更细节的信息, 请进一步参考CobarClient参考手册. Part II. Cobar Client百科大全 Chapter 2. CobarClient发起的背景 现有的Cobar方案需要单独的服务器来运行, 为了保证性能和可用性, 通常最少需要两台独立服务器.国际站应用方出于扩展和可用性等因素考虑, 希望一种不依赖于独立服务器的Cobar解决方案, 鉴于此, 决定开发Cobar的Client版本, 该版本主要面向小规模的数据库sharding集群访问, 因现有的Cobar已经在中文站等多个项目中成功应用并实施, 如果CobarClient无法满足进一步的需求,可以转而使用现有的Cobar方案. 所以, CobarClient的使用原则上只限定于某些特定场景. Chapter 3. CobarClient最初需求 CobarClient需要满足以下需求: 可以支持垂直和水平数据切分数据库集群的访问; 支持双机热备的HA解决方案, 应用方可以根据情况选用数据库特定的HA解决方案(比如Oracle的RAC),或者选用CobarClient提供的HA解决方案. 小数据量的数据集计(Aggregation), 暂时只支持简单的数据合并. 数据库本地事务的支持, 目前采用Best Efforts 1PC模式的事务管理. 数据访问操作相关SQL的记录, 分析等.(可以采用国际站现有Ark解决方案,但CobarClient提供扩展的切入接口) Chapter 4. CobarClient方案之间的权衡 4.1. JDBC API层次的解决方案 4.2. DAL层次的解决方案 4.3. 特定国际站场景的解决方案 CobarClient的实现方案可以从多个角度进行考虑, 我们暂且选择三种方案进行推演. 4.1. JDBC API层次的解决方案 因为现有的Cobar解决方案通过SQL解析来实现了shards间的路由功能, 所以, 自然而然的, 大家会马上联想到在JDBC Driver层次进行同样的封装,然后也是通过SQL解析的方式来实现路由功能. 首先这种方案是可以实现的, 但工期也绝对不会像想象的那么短. 要走这条路, 我们不可能通过封装或者拦截几个JDBC接口就很容易的搞定, 我们需要实现一整套的JDBC规范,这无论从开发还是测试方面考虑,投入的时间都会很多. 最初我们尝试只拦截Connection, Statement的相关方法来获取SQL并进行解析等工作,但发现相关方法调用的lifecycle的不匹配问题, 方法调用的trace问题, 数据库metadata等都会造成实现过程中的“尴尬 ” 和难行. 但不管怎么样, 完全的实现一套JDBC规范的API,原则上来说可以实现类似于现有Cobar解决方案类似的方案. 4.2. DAL层次的解决方案 要实现数据方案的路由功能, 我们也可以在数据访问层做文章. 从DAL层做文章的好处在于, 我们可以规范开发流程, 简化路由功能的实现, 而且, 不管将来增加更多的shards或者其它异构的存储, 比如KV store, DAL层都可以屏蔽这些变化, 使得应用程序不受任何影响. 如果采用DAL层的解决方案, 我们可以将sharding策略和规则“外部化 ” , 通过统一的配置(Annotation也好, 外部XML之类配置文件也好)来定义路由规则, 路由规则可以根据DO的类型以及相关属性进行定义, 定义简单又不失灵活性, 完全不用引入SQL解析之类的复杂性. 但基于DAL层次的解决方案对现有网站的应用来说, 冲击性太大,所以, 这虽然是个方向,但短期内无法有效施行. 4.3. 特定国际站场景的解决方案 考虑到工期以及兼容性等因素, 我们可以考虑介于JDBC API层次的解决方案和DAL层次的解决方案之间的一种解决方案. B2B内部数据访问全部采用iBatis进行, 为了提高开发效率,自然也采用了Spring提供的SqlMapClientTemplate进行数据访问逻辑的开发. 要较少的侵入现有应用, 我们可以考虑对SqlMapClientTemplate做手脚, 既然所有的数据访问都通过该类走,那么就在该类中插入路由逻辑, 根据数据访问请求的属性指定路由规则, 然后将符合路由规则的数据访问请求路由到相应的shard上去. 这实际上就是我们现在第一阶段采用的解决方案. Chapter 5. Cobar Client参考文档(Cobar Client Reference Documentation) 5.1. 鸟瞰Cobar Client现有架构实现 5.2. CobarSqlMapClientTemplate详解 5.2.1. 多数据源依赖管理(Multiple DataSources Management) 5.2.2. 数据访问请求路由(Routing In CobarSqlMapClientTemplate) 5.2.3. SqlAuditing 5.2.4. 其它配置与特性解释(Other Configuration or Features Explained) 5.3. MultipleDataSourcesTransactionManager详解 5.3.1. MultipleDataSourcesTransactionManager依赖的多数据源管理 5.1. 鸟瞰Cobar Client现有架构实现 CobarClient现有方案的架构如下图所示: 架构中主要侧重解决两个方面的问题: 数据访问请求的路由. 通过扩展Spring提供的SqlMapClientTemplate来切入进行扩展, 我们提供了自定义的CobarSqlMapClientTemplate, 并结合相应的Router支持来实现数据访问请求的路由功能, 并且尽量保持现有应用代码的兼容. 应用的迁移工作基本上只要替换注入的SqlMapClientTemplate实现类即可. 多数据源访问过程中的事务管理. 因为两阶段提交的分布式事务会严重影响应用的性能, 所以, 根据网站方需求,我们退而求其次, 采用Best Effort 1PC Pattern的事务策略, 提供了基于该Pattern的一个事务管理器实现MultipleDataSourcesTransactionManager, 该事务管理器扩展自Spring的AbstractPlatformTransactionManager, 应用程序迁移的时候只需要替换使用的事务管理器实现类即可.该事务管理器实现最大程度上保证事务管理的性能损失与数据一致性之间的一个合理权衡. 另外, 我们也通过AOP实现了数据源之间的HA,以及延迟加载数据库连接以保证资源的有效使用等功能, 这些在以上架构图中都有所体现. 鉴于CobarClient的两个主要关注点, 我们将对这两个关注点对于的主要组件进行详细的说明, 下面是详细内容, 各位看官上眼了... 5.2. CobarSqlMapClientTemplate详解 CobarSqlMapClientTemplate扩展了Spring的SqlMapClientTemplate, 主要在 SqlMapClientTemplate的基础之上添加了数据访问请求的路由功能, 以便应用程序可以透明的访问数据库切分后的各个数据库节点. 除此之外, CobarSqlMapClientTemplate也提供了一些附加的功能, 以方便应用的监控和使用. 下面我们分部分阐述CobarSqlMapClientTemplate的相关功能. 5.2.1. 多数据源依赖管理(Multiple DataSources Management) 在没有进行数据库切分之前, 应用程序使用Spring的SqlMapClientTemplate进行数据访问只需要为其提供单一的数据源引用, 类似于: public interface ICobarDataSourceService { Map com.alibaba.cobar.client.datasources.DefaultCobarDataSourceService, 通过 DefaultCobarDataSourceService, 我们可以集中管理各个数据源, 并将他们注入给CobarSqlMapClientTemplate使用. 常见的CobarSqlMapClientTemplate和其ICobarDataSourceService依赖的配置情况如下所示: class=\ class=\ class=\ com.alibaba.cobar.client.datasources.DefaultCobarDataSourceService的配置, 我们需要通过 “dataSourceDescriptors ” 属性, 为其注入一组 com.alibaba.cobar.client.datasources.CobarDataSourceDescriptor, CobarDataSourceDescriptor主要负责对相应的数据源进行描述, 其主要配置信息包括: identity. 数据分区的唯一标志, 该标志不可与其它数据分区的标志冲突, 在定义路由规则的时候, 数据分区标志将成为路由规则的一部分. targetDataSource. 主要目标数据源的依赖引用, 通常意义上, 应用启动的时候该数据源必须是Active的. targetDetectorDataSource. 主要目标数据源伴随的HA探测用数据源, 主要用于检测主要目标数据源的状态, 通常指向与主要目标数据源相同的目标数据库, 但数据库连接池要单独配置, 以防止相互干扰.(以上配置中引用了同一个数据源引用, 只是为了演示的方便) standbyDataSource. 与主要目标数据源并列的备用数据源, 当主要目标数据源出现问题之后, 如果启用了CobarClient的HA功能支持, CobarClient将自动将数据访问切换到该备用数据源上. standbyDetectorDataSource. 备用数据源对应的HA探测用数据源, 存在的目的参见targetDetectorDataSource的说明. poolSize. CobarSqlMapClientTemplate需要根据每个目标数据源的数据库连接的数量来创建相应的线程池以便提高并发处理性能, poolSize可以帮助CobarSqlMapClientTemplate决定创建的线程池的大小,如果配置的时候该项不做配置的话, 默认情况下将以CPU内核的数量乘以5作为默认大小. Note 因为当前网站的数据源配置都是通过JNDI进行, CobarClient无法统一取得数据库连接等相关信息, 也就无法根据同一份配置信息自行创建相应的数据库连接池, 所以, 只好需要应用程序方针对每一个目标数据源再多配置一个用于HA状态探测用的数据源引用. 配置实例中使用了C3P0作为容器内的数据源定义, 但CobarClient只依赖标准的DataSource接口, 所以并不止限于C3P0数据源类型, JNDI查找的数据源或者DBCP, 甚至自己实现的DataSource都是可以的. 当前CobarDataSourceDescriptor之所以需要这些信息是因为现在网站最主要的数据库部署结构是HA双机热备的水平切分数据库集群, 但后期如果有其它的数据库部署结构, CobarDataSourceDescriptor也可能随着数据库部署结构的调整而调整. Tip 如果不需要HA双机热备支持, 那么可以让standby(.*)DataSource指向target(.*)DataSource相同的数据源应用, 或者如果DefaultCobarDataSourceService的haDataSourceCreator没有指定的话, standbyDataSource,standbyDetectorDataSource和targetDetectorDataSource可以完全不配置. CobarDataSourceDescriptor引用的数据源可以来自JNDI绑定的数据源, 也可以来自容器内定义的数据源(如上配置所示, 为了测试,我们使用了Spring容器内定义的C3P0数据源), 甚至其它形式提供的数据源, 只要为其提供标准的JDBC API中的DataSource接口实现即可. DefaultCobarDataSourceService除了依赖一组CobarDataSourceDescriptor, 它还依赖于相应的IHADataSourceCreator来进行数据库的HA支持, 如果没有提供相应的IHADataSourceCreator实现类, DefaultCobarDataSourceService默认会使用 NonHADataSourceCreator, 即不创建支持HA的数据源. CobarClient默认提供了FailoverHotSwapDataSourceCreator以支持HA, 应用方可以根据情况提供自己的IHADataSourceCreator实现来满足特定场景需要. 5.2.1.1. Cobar Client中的HA支持(HA Support In Cobar Client) CobarClient支持基于双机热备的Failover, 该功能支持抽象为IHADataSourceCreator定义: public interface IHADataSourceCreator { DataSource createHADataSource(CobarDataSourceDescriptor descriptor) throws Exception; } 前面我们说过, DefaultCobarDataSourceService在构建最终使用的数据源的时候, 通过某个IHADataSourceCreator来构建支持热切换的数据源实例. 最常见的IHADataSourceCreator实现类有 com.alibaba.cobar.client.datasources.ha.NonHADataSourceCreator和 com.alibaba.cobar.client.datasources.ha.FailoverHotSwapDataSourceCreator, 其中, NonHADataSourceCreator更多用于测试环境或者HA支持不需要CobarClient端支持的情况(比如,数据库部署层面支持HA之后, CobarClient端的HA可以不需要),所以, 如果使用CobarClient提供的HA支持, 更多的是指依赖引用FailoverHotSwapDataSourceCreator. FailoverHotSwapDataSourceCreator支持基于主动探测形式的HA以及基于被动检测形式的HA, 这两种行为可以通过属性 “passiveFailoverEnable ” 和 “positiveFailoverEnable ” 来管理启用或者禁用, 其中, 基于主动探测形式的HA默认情况下是开启的, 而基于被动探测形式的HA是禁用的, 因为基于原来的Cobar(Server版)的现有经验, 每次取得数据库连接之后都进行状态检查会损耗性能. 要启用基于主动探测形式的HA支持, Cobar Client将Cobar(Server版)的HA方式适配借用过来, 需要你在数据库中配置相应的探测表, 并配置相应的探测用SQL. 例如, 假设数据库中建立了名为cobarha的状态探测表, 那我们可以设置如下的探测用SQL: class=\ 5.2.2. 数据访问请求路由(Routing In CobarSqlMapClientTemplate) 除了依赖某个ICobarDataSourceService进行多数据源的管理, CobarSqlMapClientTemplate的另一个主要依赖就是ICobarRouter, ICobarRouter负责将相应的数据访问请求路由到指定的数据源上去. 5.2.2.1. Router Design ICobarRouter抽象接口定义如下: public interface ICobarRouter 我们可以根据情况提供不同的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, 其一般的配置方式如下: 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) 一个最简单的路由规则定义文件内容可以如下所示: namespace 或者 sqlmap. 属于路由规则条件的一部分, 二者的唯一区别在于指定的条件明确程度不同, sqlmap直接对应每一个iBatis的SqlMap文件中某个statement的定义的id,而namespace则对应每一个iBatis的SqlMap文件中定义的namespace. 这两个元素在 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文件, 例如: 我们本着从特殊到一般的情况进行推演. 以create操作为例, 假设我们的offer数据现在分布在两台数据库上, 而根据切分规则, memberId为奇数的数据分布在数据库1上, memberId为偶数的数据分布在数据库2上, 在这一前提下, 要路由offer的创建相关的数据请求, 最明了的方式就是, 检查当前数据访问对应的sql statement是哪个, 并判断传入的参数包含的memberId是奇数还是偶数, 这样, 我们就有了以下2个路由规则定义: 有了以上的基础, 我们来变换假设场景, 我们依然是create操作, 但现在我们不是做的水平切分, 而只是做垂直切分, 也就是说, 所有的offer数据现在假设都会落在同一台数据库上, 那么, 以上的定义可以变更为: shardingExpression元素的定义, 以上rule定义就好像再说 “只要我发现sqlmap的值是com.alibaba.cobar.client.entities.Offer.create, 那就将匹配的数据访问请求路由到partition1, 而不管参数中的memberId或者其它数据具体是什么 ” . 我们将第一种形式的路由规则成为SqlActionShardingRule, 而将第二种形式的路由规则称为SqlAction(Only)Rule, 分别用于明确的指定在水平切分和垂直切分情况下的路由规则定义. 现在让我们进一步扩展场景, 显然, 除了要创建offer, 我们还要提供更新或者删除等数据操作, 那么, 自然而然的,我们就需要在SqlMap文件中定义更多的sql statement, 如下所示: 没添加一个针对某表的SqlMap文件, 就需要在路由规则定义文件中添加一系列的CURD操作对应的路由定义, 从使用的角度来看, 很繁琐; 通常针对某个表的操作, 切分规则都是相同的, 不管具体数据访问操作是什么, 也就是说, 通常定义一套路由规则, 原则上来讲应该可以满足CURD多个数据操作的路由. 鉴于以上两点,我们又引入了NamespaceShardingRule和Namespace(Only)Rule的概念. NamespaceShardingRule允许我们基于SqlMap中的namespace和水平切分规则进行路由规则的定义, 同样针对最初的切分规则, 即memberId为奇数的数据落在数据库1上, 而 memberId为偶数的数据落在数据库2上, 那不管其操作是创建还是更新, 只要数据访问对应的sql statement落在指定的namespace下(对应我们的情况就是 com.alibaba.cobar.client.entities.Offer命名空间), 并且数据访问参数符合指定的切分规则, 我们就可以正确的路由数据访问请求, 最终我们可以给出如下的路由规则定义: SqlActionShardingRule和SqlAction(Only)Rule的差别类似, 我们也可以只使用Namespace(Only)Rule: 现在, 定义在com.alibaba.cobar.client.entities.Offer命名空间下的所有sql statement, 将全部被路由到partition1数据库执行. 可以看到, 从SqlActionShardingRule到SqlAction(Only)Rule, 一直到NamespaceShardingRule和Namespace(Only)Rule, 路由规则涵盖的面是从特殊到一般层面逐步放开的, 如果针对某个sql statement有特殊的路由需求, 那么可以根据情况添加相应的SqlActionShardingRule或者SqlAction(Only)Rule, 而如果多个sql statement拥有相近或者相同的路由需求, 那么, 就可以根据情况归纳并添加相应的NamespaceShardingRule或者Namespace(Only)Rule, 总之, 这四种类型的Rule类型可以组合使用, 全面的覆盖整个基于iBatis的数据访问请求的路由. Tip 在定义路由规则的过程中,可以从一般情况下的NamespaceShardingRule或者 Namespace(Only)Rule着手, 首先定义一般情况下的路由规则, 然后在根据某些特殊数据访问请求, 进一步添加SqlActionShardingRule或者SqlAction(Only)Rule类型的路由规则. CobarClientInternalRouter在进行路由的时候, 将首先进行特殊情况下的路由规则匹配, 当找不到匹配规则的时候, 在进一步的使用一般的路由规则作为后备规则进行匹配. 5.2.2.2.3. 自定义路由规则函数(Custom Rule Functions) 常见的水平切分规则有: 基于范围的切分, 比如 memberId > 10000 and memberId < 20000 基于模数的切分, 比如 memberId8==1 或者 memberId8==2 或者... 基于哈希(hashing)的切分, 比如hashing(memberId)==someValue等 另外, 还有诸如predicate-based partitioning等, 为了满足不同切分规则定义的需要, 我们运行在路由规则定义的时候, 在shardingExpression中使用自定义的路由规则函数. 下面我们以一个简单的实例来说明在Cobar Client中如何自定义使用路由规则函数. 假设我们要按照某种hashing算法对memberId进行散列, 并根据散列的值进行路由, 那么首先,我们需要定义一个函数类, 该类将根据传入的memberId返回相应的散列结果: public class Hashing{ ... int apply(Long memberId){ // perform real logic here. } } 有了该函数定义,我们希望在shardingExpression中使用它, 那首先我们需要注册该函数, 这通过CobarInteralRouterXmlFactoryBean的 “functionsMap ” 属性进行: 有了以上准备之后, 我们就可以在shardingExpression中使用该自定义函数了: 5.2.3. SqlAuditing CobarSqlMapClientTemplate提供了针对SQL的分析和记录扩展接口,但没有给出相应的实现, 因为国际站现在可以通过Ark项目来完成同样的目的, 但如果需要, 可以给出一个ISqlAuditor接口实现, 然后注入给CobarSqlMapClientTemplate. ISqlAuditor接口定义很简单: public interface ISqlAuditor { void audit(String id, String sql, Object sqlContext); } 其中, 参数\标志执行的iBatis的sqlmap的id; 参数 “sql ” 表示id对应的SQL, 如果id对应的SQL是DynamicSql的话, 该参数为null; 最后参数sqlContext对应具体传入的参数对象. 应用程序可以根据具体场景来决定如何实现某个ISqlAuditor以及如何使用这些参数.为了不影响性能, 提供的ISqlAuditor尽量采用异步的方式进行处理, 不要同步阻塞后续的数据访问请求的处理. 如果为CobarSqlMapClientTemplate注入某个ISqlAuditor的实现, 那么默认情况下 CobarSqlMapClientTemplate会检查用户是否同时注入了一个伴随的ExecutorSerivce, 该伴随的ExecutorService主要是为了避免用户提供的ISqlAuditor没有进行合适的异步处理策略从而拖累CobarSqlMapClientTemplate的情况发生, 如果用户没有提供这样一个ExecutorService, 那CobarSqlMapClientTemplate会默认初始化一个拥有一个worker thread的ExecutorService. 原则上用户不需要干预该ExecutorService, 但如果调整该参数对CobarSqlMapClientTemplate的性能有帮助的话,那可以通过 sqlAuditorExecutor 属性来注入一个外部的ExecutorService. 5.2.4. 其它配置与特性解释(Other Configuration or Features Explained) 5.2.4.1. 记录长时间运行的SQL功能 应监控需求, 我们在CobarSqlMapClientTemplate中加入了记录长时间运行的SQL功能, 该功能默认情况下为不开启,如果要开启该功能, 可以通过设置 profileLongTimeRunningSql 属性来完成. 设置 profileLongTimeRunningSql 的同时, 我们同时要求提供监控的SQL运行时间的限定标准, 即 longTimeRunningSqlIntervalThreshold , 如果用户提供的 longTimeRunningSqlIntervalThreshold小于或者等于零, 在CobarSqlMapClientTemplate初始化的时候将抛出异常, 以阻止用户使用非状态完备的CobarSqlMapClientTemplate实例. 配置该功能的简单实例如下: class=\ ... 某些情况下, 应用程序可能会通过 “INSERT INTO tab(..) VALUES(..), (..), (..), (..)... ” 形式的SQL进行批量的数据插入, 为了支持这种情况, CobarSqlMapClientTemplate允许通过BatchInsertTask来提交批量的插入数据, 当CobarSqlMapClientTemplate发现在insert(..)的时候用户传入的是BatchInsertTask类型的参数的话, 它首先会根据路由规则对提交的批量数据进行重新归类, 将发送到不同DataSource的数据归类到不同的队列中, 归类完成之后, 再并行的提交给不同的DataSource执行.
正在阅读:
Spring+iBatis 的多库横向切分简易解决思路05-29
圣约翰科技大学学生奖惩办法05-15
希伯来书课程讲义0310-01
结合梁斜拉桥索力优化方法的研究11-11
数学-行程问题05-26
思想道德修养与法律基础期末考试题及答案(2022汇总题库)03-27
第三章 航迹推算与陆标定位10-21
职高拓展模块下第3单元测试A卷(有答案)10-05
大三毕业生个人总结(多篇)12-22
寂寞梧桐深院锁清秋02-14
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 切分
- 横向
- 简易
- 思路
- 解决
- Spring
- iBatis
- 2012年黠鼠赋自测练习_答案
- 碧护各个作物的使用方法及效果
- Nachos同步机制实习报告
- 高2013级抓高三踩线生方案
- 03G101-1问题汇总
- 企业突发环境风险评估报告详解
- 天津大学18秋《土力学与基础工程》在线作业二1(100分)
- 政府请示
- 《分数除法(二)》教学设计
- 12、无机化学万题库(填空题)(7-9)
- 马铃薯收获机的设计
- 歌颂政协诗歌朗诵
- 某村在党建会议上的表态发言
- 2015年上海银行业案件防控新规知识竞赛的题库(附答案)
- 《四川什邡经济开发区控制性详细规划(修编)》
- pyqt5 python Gui入门教程
- 苏州市高新区2015届中考数学二模试卷含答案解析
- 上市公司管理舞弊案例分析及审计策略 ---------以吉林紫鑫
- (10课时完整版)六年级上册数学复习教案1
- 商务英语句子