saas 多租户系统数据隔离方案

关注WX公众号: commindtech77, 获得数据资产相关白皮书下载地址

  1. 回复关键字:数据资源入表白皮书

下载 《2023数据资源入表白皮书》

  1. 回复关键字:光大银行

下载 光大银行-《商业银行数据资产会计核算研究报告》

  1. 回复关键字:数据资产估值

下载 《商业银行数据资产估值白皮书》

  1. 回复关键字:上海银行

下载 上海银行《商业银行数据资产体系白皮书》

  1. 回复关键字:商业银行数据资产管理

下载 《商业银行数据资产管理体系建设实践报告》

一、背景

网上一堆 saas多租户系统数据隔离方案的文章,本文着重于生产环境实践

二、怎样区分租户

有3种方式:

  1. 通过不同的访问url来区分;
  2. 相同的访问url,由用户输入租户ID;
  3. 相同的访问url,用户登陆后,查询租户ID;
方案 优点 缺点
通过不同的访问url来区分 1. 不用登陆; 2. 不同租户下面的用户名允许重复 用户需要记住url
相同的访问url,由用户输入租户ID 1. 不用登陆; 2. 不同租户下面的用户名允许重复 用户需要记住租户ID
相同的访问url,用户登陆后,查询租户ID 不需要记住租户ID; 1. 需要用户登陆,才能获取租户ID; 2. 用户名不能一样,否则会冲突;

阿里云、腾讯云都是使用第2种方案

阿里云子账号登陆界面

腾讯云子账号登陆界面

三、 3种数据隔离方案架构

  1. 数据库表通过租户ID字段来区分

说明:图片不是原创,在网上找的

  1. 独立的数据库(schema)

说明:图片不是原创,在网上找的

  1. 独立数据库实例

说明:图片不是原创,在网上找的

方案 优点 缺点
数据库表通过租户ID字段来区分 (1)成本低,支持的租户多; (2)实现简单,直接使用mybatis plus的TenantLineInnerInterceptor拦截器即可; (3)系统升级最方便,表变更只要执行一次即可; (4)运营做数据分析方便,不同将多个库的数据汇总分析; (1)数据隔离性差; (2)所有数据存在一起,性能随着数据的增加会变得越来越差;
独立的数据库(schema) (1)成本较低,支持的租户较多; (2)性能够好,当存在性能问题时,迁移到独立数据库实例,程序不需要改动; (3)数据隔离性好; (1)系统升级不方便,需求所有数据库都执行一次表变更的sql。随着租户增加,运维的工作量会越来越多; (2)增加一个租户,需要创建一个新的数据库,增加运维的工作量; (3)增加一个租户时,要插入一些初始化数据,开发、运维之间,要维护一个初始化数据sql文件。生产中,经常会出现由于缺少部分初始化数据,导致新租户异常的情况; (4)运营做数据分析时,不方便;
独立数据库实例 (1)性能好,可以横向扩容。可以针对租户的性能需求,配置不同性能的数据库实例。例如,租户A的数据多,用户多,要求性能高,数据库实例的配置可以分配更多的内存、更高频率CPU;租户B的数据少,用户少,性能要求低,数据库实例的配置低一些没关系; (2)数据隔离性好; (1)系统升级不方便,需求所有数据库都执行一次表变更的sql。随着租户增加,运维的工作量会越来越多; (2)增加一个租户,需要创建一个新的数据库,增加运维的工作量; (3)增加一个租户时,要插入一些初始化数据,开发、运维之间,要维护一个初始化数据sql文件。生产中,经常会出现由于缺少部分初始化数据,导致新租户异常的情况; (4)运营做数据分析时,不方便;

四、生产环境实践

在公司的项目中,通过团队的讨论,最终决定使用数据库表通过租户ID字段来区分的方案。原因如下:

  1. 当时项目刚启动,人手不足,希望成本(服务器成本、运维成本)尽可能低;
  2. 系统对数据隔离性要求不高,同时预计的数据量不太;
  3. 后期数据库如果存在性能问题,可以改用tidb横向扩容;
  4. 产品要分析租户的数据(公司的运营管理后台),如果租户数据分到不同的数据库(或者数据库实例),数据统计分析会很不方便;

五、生产实践遇到的问题

  1. 公司采用通过表增加tenantId字段来做数据隔离,采用mybatis plus的TenantLineInnerInterceptor拦截器,在查询时,自动加上tenantId查询条件,在插入数据时,自动填上用户的tenantId。
  2. 存在一些表(例如一些配置参数表),所有租户都会用到,而且都一样的。这些表在系统迭代过程中,数据会不断增加。如果也加上tenantId(即每个租户一份数据),会导致运维工作增加。例如,每增加一个租户,都要copy一份这些数据;新插入一条数据,要查询系统所有租户ID,给每个租户都增加一条数据。如果忘记这个操作,会导致部分租户异常。这个可以通过重写mybatis plus的TenantLineInnerInterceptor拦截器的ignoreTable方法,忽略指定的表,解决这个问题。
  3. 肯定要有tenantId(才知道哪个用户是哪个租户下面的),登陆接口要查用户表,但此时不知道用户是哪个租户下面的,mybatis plus的TenantLineInnerInterceptor拦截器查询时,会自动增加tenantId查询条件,会导致查询不到这个客户。可以通过查询用户的mybatis接口的方法上,加上@InterceptorIgnore(tenantLine = "1")注解即可忽略TenantLineInnerInterceptor拦截器;
    InterceptorIgnore注解,请参考mybatis plus的官方文档

插件主体 | MyBatis-Plus​baomidou.com/pages/2976a3/#mybatis-config-xml

相关推荐
dingdingfish1 分钟前
JSON 系列之1:将 JSON 数据存储在 Oracle 数据库中
oracle·json·database
小蜗牛慢慢爬行22 分钟前
如何在 Spring Boot 微服务中设置和管理多个数据库
java·数据库·spring boot·后端·微服务·架构·hibernate
hanbarger25 分钟前
nosql,Redis,minio,elasticsearch
数据库·redis·nosql
微服务 spring cloud1 小时前
配置PostgreSQL用于集成测试的步骤
数据库·postgresql·集成测试
先睡1 小时前
MySQL的架构设计和设计模式
数据库·mysql·设计模式
弗罗里达老大爷1 小时前
Redis
数据库·redis·缓存
仰望大佬0072 小时前
Avalonia实例实战五:Carousel自动轮播图
数据库·microsoft·c#
学不透java不改名2 小时前
sqlalchemy连接dm8 get_columns BIGINT VARCHAR字段不显示
数据库
一只路过的猫咪2 小时前
thinkphp6使用MongoDB多个数据,聚合查询的坑
数据库·mongodb