当前位置: 首页 > news >正文

SaaS多租户系统架构设计

前言:多租户是SaaS(Software-as-a-Service)下的一个概念,意思为软件即服务,即通过网络提供软件服务。SaaS平台供应商将应用软件统一部署在自己的服务器上,客户可以根据工作的实际需求,通过互联网向厂商租用所需的应用软件服务,按定购的服务多少和时间长短向厂商支付费用,并通过互联网获得SaaS平台供应商提供的服务。SaaS服务尤其利于一些中小企业,以低成本实现自己的软件需求。


 一、SaaS多租户简介

1.1、SaaS多租户概念

多租户技术是一种软件架构技术,它是在探讨与实现如何于多用户的环境下共用相同的系统或程序组件,并且仍可确保各用户间数据的隔离性。它是为共用的数据中心内如何以单一系统架构与服务提供多数客户端相同甚至可定制化的服务,并且仍可保障客户的数据隔离。简单来说是一个单独的实例可以为多个组织服务。

1.2、SaaS多租户的优势

  • 开发和运维成本低

  • 按需付费,节约成本

  • 即租即用,软件版本更新快

  • 故障排查更及时

  • 大数据和AI的能力支持更强大

1.3、为什么要搭建多租户系统?

多租户是SaaS领域的特有产物,探究何为多租户需回归到对SaaS的理解上。

SaaS服务是指部署在云上的,客户可以按需购买,并通过网络请求就能获取到的服务;也就是说,在这样的场景下,会有N个客户同时使用同一套SaaS服务。

那么对SaaS服务供应商来说,构建SaaS体系需要完成两部分工作:上层服务+底层多租户系统。

上层服务是供应商对外售卖的软件服务,其可以为客户创造价值、为公司带来营收;而底层多租户系统则是SaaS模式实现的具体方式,公司在对外售卖SaaS服务时,需要考虑如何实现客户之间的数据隔离、服务的权限控制、计费管理等;因此需要引入多租户概念来解决上述问题。

通过多租户系统,公司可以更好的管理客户和上层服务,客户也可以更好的使用软件服务。这也就是多租户系统存在的意义了。

1.4、多租户模型

如图所示,涉及主要模型有以下几类:

(1)租户:指一个企业客户或是个人客户,租户之间数据与行为隔离,上下级租户间通过授权实现数据共享。每个租户只能操作归属或授权给该租户的数据;

(2)组织:如果租户是一个企业客户,通常就会拥有自己的组织架构;

(3)用户:租户下的具体使用者,拥有用户名、密码、邮箱等账号信息的自然人;

(4)角色:用户操作权限的集合;

(5)员工:组织内的某位员工;

(6)解决方案:为了解决客户的某类型业务问题,SaaS供应商一般都将产品和服务组合在一起,为客户提供整体的打包方案;

(7)产品能力:能够帮助客户实现场景解决方案闭环的能力;

(8)资源域:用来运行1个或多个产品应用的一套云资源环境;

(9)云资源:SaaS产品一般都部署在各种云平台上,例如阿里云、腾讯云、华为云等。对这些云平台提供的计算、存储、网络、容器等资源,抽象为云资源。


 二、SaaS多租户的数据隔离设计方案  

2.1、三种多租户数据隔离方案

多租户对于用户来说,最主要的一点就在于数据隔离。不能出现,我登了A用户单位的号,但是看到了B用户单位的数据。因此,多租户的数据库设计方案和代码实现就相当有必要考虑了。

目前开发者们普遍接受的SaaS多租户设计方案,常见的大概就3种:

即为每个租户提供独立的数据库、独立的表空间、按字段区分租户,每种方案都有其各自的适用情况。

  • 一个租户独立一个数据库

一个租户独立使用一个数据库,那就意味着我们的SaaS系统需要连接多个数据库,这种实现方案其实就和分库分表架构设计是一样的,好处就是数据隔离级别高、安全性好,毕竟一个租户单用一个数据库,但是物理硬件成本,维护成本也变高了。

  • 独立的表空间

这种方案的实现方式,就是所有租户共用一个数据库系统,但是每个租户在数据库系统中拥有一个独立的表空间。

  • 按租户id字段隔离租户

这种方案是多租户方案中最简单的数据隔离方法,即在每张表中都添加一个用于区分租户的字段(如tenant_id或org_id啥的)来标识每条数据属于哪个租户,当进行查询的时候每条语句都要添加该字段作为过滤条件,其特点是所有租户的数据全都存放在同一个表中,数据的隔离性是最低的,完全是通过字段来区分的,很容易把数据搞串或者误操作。

2.2、三种数据隔离架构设计的对比如下:

隔离方案成本支持租户数量优点缺点
独立数据库系统数据隔离级别高,安全性,可以针对单个租户开发个性化需求数据库独立安装,物理成本和维护成本都比较高
独立的表空间较多提供了一定程度的逻辑数据隔离,一个数据库系统可支持多个租户数据库管理比较困难,表繁多,同时数据修复稍复杂
按租户id字段区分维护和购置成本最低,每个数据库能够支持的租户数量最多隔离级别最低,安全性也最低

大部分公司都是采用第三种多租户设计方案:按租户id字段隔离租户 架构设计实现多租户数据隔离的。

2.3、MyBatis-Plus多租户插件优雅实现数据隔离​

该系统只有一个数据库,所有租户共用数据表。在每一个数据表中增加一列租户ID,用以区分租户的数据。增删查改时,一定要带上租户ID,否则就会操作到其他租户的数据。因此,这里的设计一定要重点考虑。

  我们要保证的就是一定不要忘记带上租户ID。一个很好的方案就是通过AOP的方案,隐式的为我们的每一个SQL带上这个租户ID。我个人是更喜欢使用MyBatisPlus来操作数据库的。它提供了插件的机制,我们可以通过拦截它提供的四大组件的某些对象,某些方法,来操作SQL,动态的为我们的SQL拼接上租户ID字段。

  当然,MyBatis-Plus高版本提供了更加方便的拦截器,并且已经将多租户插件放入JAR包,我们只需稍加实现,并将该插件加入到MyBatis的拦截器链中,就可以不用再显式的拼接租户ID字段了,降低了出错的概率。

篇幅有限,如果有兴趣查看我写的这篇文章:MyBatisPlus实现多租户功能


参考链接:

数云融合丨 一文让你弄懂多租户数据库设计⽅案

SaaS架构:多租户系统架构设计

SaaS模式下,多租户系统数据隔离实现方案

谈谈对多租户SaaS系统的简要理解 - 知乎

相关文章:

SaaS多租户系统架构设计

前言:多租户是SaaS(Software-as-a-Service)下的一个概念,意思为软件即服务,即通过网络提供软件服务。SaaS平台供应商将应用软件统一部署在自己的服务器上,客户可以根据工作的实际需求,通过互联网…...

Java自定义捕获异常

需求分析 ElectricalCustomerVO electricalCustomerVO new ElectricalCustomerVO(); electricalCustomerVO.setElcNumber(chatRecordsLog.getDeviceNumber()); List<ElectricalCustomerVO> electricalCustomerlist electricalCustomerMapper.selectElectricalCustomer…...

力扣--数组类题目27. 移除元素

给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 示例 1&#xff1a; 输入&#xff1a;nums [3,2,2,3], val 3 输出&#xff1a;2, nums [2,2] 解释&#xff1a;函数应该返回新的长度 2, 并且 n…...

实际并行workers数量不等于postgresql.conf中设置的max_parallel_workers_per_gather数量

1 前言 本文件的源码来自PostgreSQL 14.5&#xff0c;其它版本略有不同 PostgreSQL的并行workers是由compute_parallel_worker函数决定的&#xff0c;compute_parallel_worker是估算扫描所需的并行工作线程数&#xff0c;并不是您在postgresql.conf中设置的max_parallel_work…...

java定位问题工具

一、使用 JDK 自带工具查看 JVM 情况 在我的机器上运行 ls 命令&#xff0c;可以看到 JDK 8 提供了非常多的工具或程序&#xff1a; 接下来&#xff0c;我会与你介绍些常用的监控工具。你也可以先通过下面这张图了解下各种工具的基本作用&#xff1a; 为了测试这些工具&#x…...

【Java】基础入门 (十六)--- 异常

1.异常 1.1 异常概述 异常是指程序在运行过程中出现的非正常的情况&#xff0c;如用户输入错误、除数为零、文件不存在、数组下标越界等。由于异常情况再程序运行过程中是难以避免的&#xff0c;一个良好的应用程序除了满足基本功能要求外&#xff0c;还应具备预见并处理可能发…...

[javaWeb]Socket网络编程

网络编程&#xff1a;写一个应用程序,让这个程序可以使用网络通信。这里就需要调用传输层提供的 api。 Socket套接字 传输层提供协议&#xff0c;主要是两个: UDP和TCP 提供了两套不同的 api&#xff0c;这api也叫做socket api。 UDP和 TCP 特点对比&#xff1a; UDP: 无连…...

<MySon car=“宝马“ :money=“money“></MySon>有没有冒号

为什么car"宝马"没有&#xff1a; 但是 :money"money"就有&#xff1a; <script setup> import {ref} from vue import MySon from /components/MySon.vueconst money ref(100) </script><template><h3>father</h3><My…...

netty(三):NIO——多线程优化

NIO多线程优化 使用Boss线程来处理accepct事件使用Worker线程来处理读写事件&#xff0c;可以创建多个worker线程 package com.review;import lombok.extern.slf4j.Slf4j;import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.*; impor…...

Linux操作系统--linux概述

1.Linux概述 Linux&#xff0c;全称GNU/Linux&#xff0c;是一种免费使用和自由传播的类UNIX操作系统&#xff08;OS&#xff09;。简单的说就是一种操作系统。在日常中常见的操作系统有一下三种: 2.linux起源和背景 (1).linux的诞生 linux操作系统是由李纳斯托瓦兹&#xf…...

数组中出现次数超过一半的数字

⭐️ 题目描述 &#x1f31f; OJ链接&#xff1a;数组中出现次数超过一半的数字 思路&#xff1a; 采用投票计数的方式&#xff0c;我们可以把每个数字都看成一次投票并且计数&#xff0c;那么最后剩下来的就是数组中数字出现次数最多的那一个。比如 { 1,2,3,2,2,2,5,4,2 } &a…...

网络优化工程师,你真的了解吗?

一、5G网络优化工程师到底是什么&#xff1f; 5G&#xff0c;就是我们通常所说的第五代移动通信标准&#xff0c;属于目前最热门的新技术趋势。随着2019年5G技术进入正式的商用阶段&#xff0c;拥有广阔的发展前景&#xff0c;备受瞩目。“5G工程师”这个词是一个概念词&#x…...

git 的常用命令

git是一个版本管理器&#xff0c;是程序员必备工具之一&#xff0c;其主分为三个区&#xff1a; 工作区&#xff1a; 暂存区&#xff1a; 仓库&#xff1a; 通过保持软件版本&#xff0c;分支&#xff0c;合并&#xff0c;等多种版本操作&#xff0c;使软件能在自己想要的版本…...

linux如何拷贝文件,删除多余的一级目录,用*号代替所有文件

加上*&#xff0c;代表目录下的所有文件 mv /home/user/dir1/dir1/* /home/user/dir1/可以使用mv命令的通配符来去掉一层目录。 例如&#xff0c;假设有一个名为/home/user/dir1/dir2/file.txt的文件&#xff0c;要将它移动到/home/user/dir2/目录下并去掉dir1目录&#xff0…...

springboot使用properties

一、方式1&#xff1a; 1.1.配置类&#xff1a; package cn.zyq.stater.config;import cn.zyq.stater.bean.User4; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework…...

Android中获取手机SIM卡的各种信息

通过以下工具类方法可以获取到手机SIM的各种信息数据&#xff01;&#xff01;&#xff01; package com.utils; import android.telephony.TelephonyManager; import com.baidu.platform.comapi.map.E; import org.json.JSONArray; import org.json.JSONObject; import java.…...

matlab 根据索引提取点云

目录 一、语法二、说明三、名称-值对应参数1、输入参数2、输出参数四、代码示例五、结果展示六、参考链接一、语法 ptCloudOut = select(ptCloud,indices) ptCloudOut = select(ptCloud,row,column...

蓝芯、四川邦辰面试(部分)

蓝芯 HTTP请求经过MQ异步处理后&#xff0c;怎样返回结果呢&#xff1f;grpc比起spring cloud的优缺点&#xff1f; 四川邦辰 SkyWalking的埋点具体是怎么操作的&#xff1f;newBing: SkyWalking支持两种埋点方式&#xff1a;自动埋点和手动埋点。自动埋点是指通过SkyWalking…...

openCV实战-系列教程13:文档扫描OCR识别下(图像轮廓/模版匹配)项目实战、源码解读

&#x1f9e1;&#x1f49b;&#x1f49a;&#x1f499;&#x1f49c;OpenCV实战系列总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 上篇内容&#xff1a; openCV实战-系列教程11&#xff1a;文档扫描OCR识别上&am…...

SpringBootWeb案例 Part 4

3. 修改员工 需求&#xff1a;修改员工信息 在进行修改员工信息的时候&#xff0c;我们首先先要根据员工的ID查询员工的信息用于页面回显展示&#xff0c;然后用户修改员工数据之后&#xff0c;点击保存按钮&#xff0c;就可以将修改的数据提交到服务端&#xff0c;保存到数据…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...