程序主要是通过/base/base-datacenter/base-datacenter-client
模块来实现动态数据源、多数据中心的。
为什么使用多个数据中心?
主要是为了减少单个数据中心的压力。每个公司在注册的时候,会按资源使用情况分配到不同的数据中心。
目前是按业务拆分了不同数据库,例如账户管理使用的是saas_account
数据库,流程管理使用的是saas_process
数据库。
数据源
SAAS服务端的启动数据库是saas_manage
,表saas_manage.datacenter
记录了全部数据中心,
表saas_manage.datasource
记录了不同数据中心下的数据源参数。
表saas_account.ac_company
记录了每个公司使用的数据中心。
标记需要使用的数据源
程序提供了@Database
注解,用于在包、类或方法上标注该程序需要使用的数据源名称,
例如@Database("saas_biz")
表示该方法使用的数据源是saas_biz
。当然也可以直接在模块的
src/main/resources/application.properties
文件里面配置database=xxx
。
配置的优先级是 方法 > 类 > 包 > application.properties
动态切换
通过AOP,在所有需要用到数据源的方法执行前,会检查该方法配置的数据库名+当前登录用户使用的数据中心,
然后切换到该数据源(如果不存在数据源则自动创建),执行完再切换回来。
代码在com.usoftchina.saas.dc.client.aspect.DatabaseAspect.aroundExecution
处理某个业务时,可能涉及到多个应用,每个应用用到的数据源有可能不一样。
例如审批流程结束的同时要执行业务单据的审核方法,这里需要用到saas_process
和saas_biz
两个数据源,
如果执行业务单据审核方法失败了,那么就需要回滚saas_biz
的事务,同时也要回滚saas_process
的
事务;如果审核方法执行成功了,那么就是提交saas_biz
事务,同时提交saas_process
事务。也就是说,
多个事务的提交与回滚应该是原子性的。
程序里面使用atomikos
和MysqlXADataSource
来实现分布式事务。具体使用与一般的事务一样,在方法上面加
@Transactional
注解即可。方法里面涉及的每个数据源连接都会自动创建子事务,方法正常执行完成后,会一起提交。
需要注意的是,开启了分布式事务,则存储过程里面不能开启独立事务,否则会破坏事务一致性。