最近在做SaaS应用,数据库采用了单实例多schema的架构(详见参考资料1),每个租户有一个独立的schema,同时整个数据源有一个共享的schema,因此需要解决动态增删、切换数据源的问题。
在网上搜了很多文章后,很多都是讲主从数据源配置,或都是在应用启动前已经确定好数据源配置的,甚少讲在不停机的情况如何动态加载数据源,所以写下这篇文章,以供参考。
使用到的技术
- Java8
- Spring + SpringMVC + MyBatis
- Druid连接池
- Lombok
- (以上技术并不影响思路实现,只是为了方便浏览以下代码片段)
思路
当一个请求进来的时候,判断当前用户所属租户,并根据租户信息切换至相应数据源,然后进行后续的业务操作。
代码实现
TenantConfigEntity(租户信息)
|
|
DataSourceUtil(辅助工具类,非必要)
|
|
DataSourceContextHolder
使用ThreadLocal保存当前线程的数据源key name,并实现set、get、clear方法;
|
|
DynamicDataSource(重点)
继承AbstractRoutingDataSource(建议阅读其源码,了解动态切换数据源的过程),实现动态选择数据源;
|
|
DynamicDataSourceSummoner(重点中的重点)
从数据库加载数据源信息,并动态组装和注册spring bean,
|
|
spring-data-source.xml
|
|
DynamicDataSourceAspectAdvice
利用AOP自动切换数据源,仅供参考;
|
|
其他
另外,部分信息(例如:租户配置、省市县等共用信息)是存放在公共schema里面的,也就是说一个请求里面有可能包括查询当前租户数据源和公共数据源,建议为公共数据源单独创建一个sqlSessionFactory
和sqlMapper
(分别对应xml配置里的defaultSqlSessionFactory
和defaultSqlMapper
),或干脆把公共数据源的数据单独做成一个微服务,以后水平扩展也方便。