多租户概述
多租户(Multi Tenancy/Tenant)是一种软件架构,其定义是:在一台服务器上运行单个应用实例,它为多个租户提供服务。
数据隔离方案
独立数据库
即一个租户一个数据库。
共享数据库,独立Schema
即多个或所有租户共享Database,但是每个租户一个Schema(也可叫做一个user)。
共享数据库,共享Schema,共享数据表
即租户共享同一个Database、同一个Schema,但在表中增加租户标识的数据字段。
实现方式
在MySQL没用schema和database的区分,所以上述1、2两种方案大体一致。当前选择最低成本的共享数据库,共享Schema,共享数据表方案。后续讨论全部针对于方案3展开。
简单来说,意味着每条数据都需要区分出属于哪个租户。为了减少后期开发成本,需要为用户表以及用户相关的表全都增加租户标识的字段(如tenantId)。
此时涉及与租户相关的SQL都需要拼接tenantId = ?,若手动拼接,改造过程过于繁琐。此时我们想到的方案是根据当前用户所属的租户动态的拼接SQL,恰巧MyBatis-Plus为我们提供了这样功能的插件,仅需要简单的配置即可。
MyBatis-Plus 的多租户 SQL 解析器配置
参考官方文档及demo https://mybatis.plus/guide/tenant.html
此处贴一下核心配置
@MapperScan("com.liuqitech.demo.dao")
@Configuration
public class MyBatisConfig {
/**
* 多租户的标识字段
*/
private static final String TENANT_ID_COLUMN = "TENANT_ID";
/**
* 忽略多租户的表名
*/
private static final List<String> IGNORE_TENANT_TABLES = Lists
.newArrayList("table1", "table2", "table3", "table4");
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
TenantSqlParser tenantSqlParser = new TenantSqlParser();
tenantSqlParser.setTenantHandler(new TenantHandler() {
@Override
public Expression getTenantId(boolean where) {
// TODO 此处的tenantId需要自己获取当前用户所属的租户
String tenantId = "liuqitech";
return new StringValue(tenantId);
}
@Override
public String getTenantIdColumn() {
return TENANT_ID_COLUMN;
}
@Override
public boolean doTableFilter(String tableName) {
return IGNORE_TENANT_TABLES.stream().allMatch(e -> e.equalsIgnoreCase(tableName));
}
});
paginationInterceptor.setSqlParserList(Lists.newArrayList(tenantSqlParser));
return paginationInterceptor;
}
}