摘要:多租户的含义是让多用户共用相同的系统或组件,但是又能保证各个用户之间数据是隔离的。多租户技术可以实现多个租户共用系统实例,而且同时能实现系统实例的个性化定制。
1. 多租户在数据存储上的实现方式
每个租户有自己独立的数据库
这种方式隔离级别最高,但是成本也最高。
租户共用数据库,但是有自己独立的schema(数据架构)
这种方式能支持更多的租户,但是如果出现故障,可能会使不同租户的数据之间产生牵连。
租户共用数据库,且共享schema(数据架构),通过tenant_id字段区分租户
这种方式隔离级别最低,成本也最低,但是共享程度最高。
2. 基于字段的隔离方式实践
该种方式利用的是MyBatis的插件机制。
首先引入maven依赖。
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
yml中添加配置项。
mybatis-plus:
configuration:
cache-enabled: true
use-generated-keys: true
default-executor-type: REUSE
use-actual-param-name: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
MyBatisPlus配置类
@Configuration
public class MyBatisConfig {
/**
* inject pagination interceptor.
*
* @return pagination
*/
@Bean
public PaginationInnerInterceptor paginationInnerInterceptor() {
return new PaginationInnerInterceptor();
}
/**
* add interceptor.
*
* @return MybatisPlusInterceptor
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// TenantLineInnerInterceptor
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
@Override
public Expression getTenantId() {
// 实际可以将TenantId放在threadLocale中(比如xxxxContext中),并获取。
return new LongValue(1);
}
@Override
public String getTenantIdColumn() {
return "tenant_id";
}
@Override
public boolean ignoreTable(String tableName) {
return false;
}
@Override
public boolean ignoreInsert(List<Column> columns, String tenantIdColumn) {
return TenantLineHandler.super.ignoreInsert(columns, tenantIdColumn);
}
}));
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
}
3. 补充
来自MyBatisPlus官方的注意点。
多租户 != 权限过滤,不要乱用,租户之间是完全隔离的!!!
启用多租户后所有执行的method的sql都会进行处理。
自写的sql请按规范书写(sql涉及到多个表的每个表都要给别名,特别是 inner join 的要写标准的 inner join)