多租户概述
多租户(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
此处贴一下核心配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| @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; }
}
|