# hube-platform-tenant **Repository Path**: jssbzg/dynamic-data-source ## Basic Information - **Project Name**: hube-platform-tenant - **Description**: 根据租户ID,动态切换数据源,多租户SaaS平台数据库拆分设计。 - **Primary Language**: Java - **License**: LGPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 4 - **Forks**: 4 - **Created**: 2022-06-02 - **Last Updated**: 2025-08-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 多租户平台设计 ## 一、平台设计 - [x] 动态数据源切换 - [x] 多数据源动态加载、卸载、监控 - [x] 数据库版本管理、脚本管理 - [x] 集成Mybatis-Plus - [ ] HikariCP监控web页面 ## 二、具体实现 ### 1、动态数据源 动态数据源部分,主要通过实现Spring的`AbstractRoutingDataSource`来实现的。 核心部分,包括`setDefaultTargetDataSource`设置默认数据源,`setTargetDataSources`设置其他数据源。 通过子类的`targetDataSources`来实现动态添加、删除。 注意,在设置完成后,需要 `afterPropertiesSet` 来刷新配置生效。 数据源的切换,通过`determineCurrentLookupKey`绑定`ThreadLocal`变量来控制。 ### 2、AOP切面 切面通过对 `autoSwitchDB`注解的切入,获取header中的租户信息(可根据需求具体定制),获取到租户信息后,通过改变全局变量`contextHolder`来动态切换。 由于系统初始化的时候,不会初始化所有的数据源,所以在进入切面的首次,会初始化一次当前租户的数据源配置。并把配置key,存到全局`dataSourceKeys`中。 ### 3、数据库同步脚本 数据库版本管理,是通过`Liquibase`来实现的。liquibase是一款用于数据库重构和迁移的开源工具,通过日志文件的形式记录数据库的变更,然后执行日志文件中的修改,将数据库更新或回滚到一致的状态。 再每次服务启用时,liquibase会检测`resources`目录下 ,`db/changelog/master-**.yml,tenant-init-**.yml`两个文件的变动,来执行数据库脚本的变更。 **注意:**对于开发要求,每次数据库字段的修改、表结构的变更、新增等DDL操作,均需按照规范格式,通过编写yml文本的方式来操作数据库,禁止直接修改数据字段。对于主数据库的操作记录在 master-init.yml中,对于租户数据库的操作记录在tenant-int.yml中。 维护好以后,每次重启服务,即自动维护多租户数据库的变更。 核心部分代码: ```java //注册liquibase for (TenantDataBaseConfigPO tenantConfig : infoList) { DynamicDataSource dynamicDataSource = (DynamicDataSource) ApplicationContextHelper.getBean(AppConstant.DYNAMIC_DATA_SOURCE); HikariDataSource dataSource = dynamicDataSource.addDataSource(tenantConfig.getTenantId(), tenantConfig.getDatabaseName(), facade.map(tenantConfig, HikariConfig.class)); SpringLiquibase liquibase = ApplicationContextHelper.getBean(SpringLiquibase.class); liquibase.setDataSource(dataSource); liquibase.setChangeLog(properties.getChangeLog()); liquibase.afterPropertiesSet(); datasourceList.add(dataSource); } ``` **关闭功能**:配置`enable:false` ```yml liquibase: master-data: change-log: classpath:db/changelog/master.xml enabled: true tenant: change-log: classpath:db/changelog/tenant.xml enabled: true ``` ### 4、hikariCP连接池监控 基于性能的原因,选择`HikariCP`数据库连接池,通过`MetricRegistry` 对核心参数进行监控。 | 指标 | 解释 | 在运维时的作用 | | :---------------------- | :------------------- | :----------------------------------------------------------- | | `ActiveConnections` | 活跃连接数 | 此数据长期保持最大连接数值的时候可以尝试扩大连接数 | | `IdleConnections` | 空闲连接数 | 此数据过高的时候可以尝试减少配置中的最小连接数 | | `MaxConnections` | 配置的最大连接数 | | | `MinConnections` | 配置的最小连接数 | | | `PendingConnections` | 排队等待连接的线程数 | 如果此数据持续飙高,表示连接池中已经没有空闲线程了 | | `TotalConnections` | 当前总连接数 | | | `ConnectionCreation` | 创建新连接的耗时 | 此数据主要反应当前服务到数据服务的网络延迟 | | `ConnectionTimeoutRate` | 创建新连接的超时 | 如果经常创建连接超时这个时候需要排查数据服务或者网络通讯是否异常 | | `Usage` | 连接被复用时长 | 此参数表示连接池中一个连接从返回连接池到再次被复用的时间间隔,表示数据访问频繁程度,对于使用较长的间隔可以尝试减少连接数 | | `Wait` | 获取连接的等待耗时 | 可以和`PendingConnections`结合分析连接池情况。 | ### 5、Mybatis-Plus集成 集成`mybatis-plus`,通过实现`MetaObjectHandler`,对数据表的`createDate、createBy、updateDate、updateBy`字段实现自动更新插入等。 ### 6、动态添加租户 动态添加租户后,通过配置数据源,即可通过`Liquibase`自动创建数据库,并完成基础数据的导入等。 ## 三、其他