Spring + iBatis 的多库横向切分简易解决思路2
?
可见, 基本上只需要替换两处配置即可完成迁移工作.
不过, 以上只是简化后的迁移场景, 实际上, 还有一些细节需要我们完善之后, 才能完全的完成整个的迁移工作.
1.1.?数据分区多数据源的依赖管理说明在单数据源的情况下, SqlMapClientTemplate(或者说它依赖的SqlMapClient)以及对应进行事务管理的DataSourceTransactionManager都会引用同一个数据源;而当应用进行数据拆分之后, 物理上将对应多个数据源, 要进行数据访问和事务管理, 我们现在必须针对数据拆分之后对应的多个数据源进行.为了同一的管理这种依赖, CobarClient提供了ICobarDataSourceService这一抽象接口用于归类管理数据拆分后对应的多个数据源, com.alibaba.cobar.client.CobarSqlMapClientTemplate和com.alibaba.cobar.client.transaction.MultipleDataSourcesTransactionManager现在将都依赖于某个ICobarDataSourceService的实现来提供对某些数据源的依赖, 这样, 最初的配置将演化为如下的形式:
也就是说, 现在MultipleDataSourcesTransactionManager和CobarSqlMapClientTemplate都有一个
DefaultCobarDataSourceService引用一组com.alibaba.cobar.client.datasources.CobarDataSourceDescriptor, 每一个com.alibaba.cobar.client.datasources.CobarDataSourceDescriptor描述了针对某一数据拆分分区的必要依赖, 这包括:
1.2.?CobarSqlMapClientTemplate其它相关配置说明
因为com.alibaba.cobar.client.transaction.MultipleDataSourcesTransactionManager属于标准的Spring的PlatformTransactionManager实现, 除了唯一特定于CobarClient的ICobarDataSourceService依赖之外, 其它都继承自Spring标准类AbstractPlatformTransactionManager, 故此其配置在这里就不做更多说明了,应用方可以参阅Spring的相关文档获取更多配置和使用信息. 下面我们主要针对CobarSqlMapClientTemplate的相关依赖进行进一步说明.
4.1.?JDBC API层次的解决方案
因为现有的Cobar解决方案通过SQL解析来实现了shards间的路由功能, 所以, 自然而然的, 大家会马上联想到在JDBC Driver层次进行同样的封装,然后也是通过SQL解析的方式来实现路由功能. 首先这种方案是可以实现的, 但工期也绝对不会像想象的那么短.
要走这条路, 我们不可能通过封装或者拦截几个JDBC接口就很容易的搞定, 我们需要实现一整套的JDBC规范,这无论从开发还是测试方面考虑,投入的时间都会很多.
最初我们尝试只拦截Connection, Statement的相关方法来获取SQL并进行解析等工作,但发现相关方法调用的lifecycle的不匹配问题, 方法调用的trace问题, 数据库metadata等都会造成实现过程中的4.2.?DAL层次的解决方案
要实现数据方案的路由功能, 我们也可以在数据访问层做文章. 从DAL层做文章的好处在于, 我们可以规范开发流程, 简化路由功能的实现, 而且, 不管将来增加更多的shards或者其它异构的存储, 比如KV store, DAL层都可以屏蔽这些变化, 使得应用程序不受任何影响.
如果采用DAL层的解决方案, 我们可以将sharding策略和规则4.3.?特定国际站场景的解决方案
考虑到工期以及兼容性等因素, 我们可以考虑介于JDBC API层次的解决方案和DAL层次的解决方案之间的一种解决方案.
B2B内部数据访问全部采用iBatis进行, 为了提高开发效率,自然也采用了Spring提供的SqlMapClientTemplate进行数据访问逻辑的开发. 要较少的侵入现有应用,我们可以考虑对SqlMapClientTemplate做手脚, 既然所有的数据访问都通过该类走,那么就在该类中插入路由逻辑, 根据数据访问请求的属性指定路由规则, 然后将符合路由规则的数据访问请求路由到相应的shard上去.
这实际上就是我们现在第一阶段采用的解决方案.
5.1.?鸟瞰Cobar Client现有架构实现CobarClient现有方案的架构如下图所示:
架构中主要侧重解决两个方面的问题:
5.2.?CobarSqlMapClientTemplate详解CobarSqlMapClientTemplate扩展了Spring的SqlMapClientTemplate,主要在SqlMapClientTemplate的基础之上添加了数据访问请求的路由功能,以便应用程序可以透明的访问数据库切分后的各个数据库节点. 除此之外,CobarSqlMapClientTemplate也提供了一些附加的功能, 以方便应用的监控和使用.下面我们分部分阐述CobarSqlMapClientTemplate的相关功能.
进行数据切分之后, 因为数据访问可能加诸在不同的数据切分分区上, 也就是说, 需要同时引用多个数据源依赖, 所以,我们需要通过某种方式来管理这多个数据源的依赖, 并将其注入给CobarSqlMapClientTemplate使用.在CobarClient中, 完成这一工作的是ICobarDataSourceService抽象:
注意, CobarSqlMapClientTemplate依然需要一个iBatis的SqlMapClient的引用,因为CobarSqlMapClientTemplate依然是一个SqlMapClientTemplate(虽然听起来有些废话).以上配置中重头戏在于com.alibaba.cobar.client.datasources.DefaultCobarDataSourceService的配置,我们需要通过
FailoverHotSwapDataSourceCreator将定时的发送该SQL到目标数据库, 对目标数据库的状态进行探测,如果超时或者抛出异常, 那么重试指定次数之后依然如此的话,FailoverHotSwapDataSourceCreator会将目标数据库热切换到备用目标数据库上去. 探测的时间间隔,探测的超市时间, 探测的重试次数等, 都可以通过相应的属性进行设置,更多这方面的信息可以参考FailoverHotSwapDataSourceCreator的javadoc文档.
CobarInteralRouterXmlFactoryBean将根据指定的xml形式的配置文件中的内容,自动构建不同类型的路由规则, 然后注入到它将最终返回的CobarClientInternalRouter实例之上.而读取,解析配置信息, 并构建不同类型路由规则等
?
5.3.?MultipleDataSourcesTransactionManager详解
根据国际站需求, CobarClient需要保证多个数据库之间的本地事务,但不接受分布式事务,因为分布式事务可能引入不必要的性能问题.在这种前提条件下,我们最终敲定使用Best Efforts 1PCPattern来实现CobarClient的事务管理.
CobarClient提供了自定义的事务管理器MultipleDataSourcesTransactionManager来支持基于BestEfforts 1PC Pattern的事务管理,MultipleDataSourcesTransactionManager接受一组数据源作为事务的目标资源,当事务开始的时候,开启所有数据源相关的本地事务, 事务提交或者回滚的时候,则同时提交或者回滚所有的本地事务.同时开始所有数据源上的本地事务,默认情况下,自然会占用每一个数据源的一个物理连接, 进而可能造成性能问题,所以,我们对依赖的数据源进行了拦截, 加入了一层LazyConnectionDataSourceProxy,该LazyConnectionDataSourceProxy将保证只有存在确切的数据访问操作的时候,才会真正的从目标数据源中获取真正的物理连接,也正如架构图中(1)和(2)所标注的那样.
实际上, 为了避免不必要的物理连接的占用, 我们也可以在事务定义中加入相应的标志数据来表明要在哪些资源之上开启本地事务,这可以通过在Service层次标注Annotation或者附带外部配置文件的形式实现.不过,可能有人会认为这会一定程度的侵入service层,所以,暂时还是采用MultipleDataSourcesTransactionManager加上LazyConnectionDataSourceProxy的组合来完成基于BestEfforts 1PC Pattern的事务管理.
总的来说,MultipleDataSourcesTransactionManager的使用其实就这么简单(有关com.alibaba.cobar.client.datasources.DefaultCobarDataSourceService的更多信息,请参考???相关内容.). 如果要了解更多配置细节,可以参考Spring的AbstractPlatformTransactionManager或者MultipleDataSourcesTransactionManager的javadoc.
Chapter?6.?CobarClient展望
希望CobarClient从更抽象的层次来屏蔽分布式数据以及不同数据存储服务之间的差异性, 所以, 我们希望提供一个统一的数据访问层(DAL), 由该DAL来规范和统一数据访问行为,同时屏蔽分布式场景下的数据访问的复杂度.另外, 随着需求的变更以及架构的演化,可以将数据的复制和同步, 缓存的接入, 实时的索引构建等等, 都可以通过我们的DAL层进行, 对于应用方来说, 他们只需要关注应用端的关注点, 而不需要关注DAL之后发生了什么,变更了什么,增加和减少了什么...