多租户系统数据隔离方案

目录

前言

数据行

数据表

基于业务场景

基于数据量

数据库

数据源表

动态数据源


前言

多租户系统是一种将多个客户的数据和应用程序分开的系统,每个客户被视为一个独立的租户,互不干扰。实现多租户系统的关键之一是确保数据的隔离。

数据隔离的方案可以分成三种:

  1. 数据行级别:所有租户的数据都在同一张表内,表中设计一个租户ID字段来区分不同租户,只需增加租户ID处理逻辑。这种方案最简单,也适用于绝大多数数据量不大,并发量也不高的小系统
  2. 数据表级别:每个租户在同一个数据库中,使用不同的数据表来存储数据,多租户操作不需要切换数据源,相对没那么复杂,但是需要为数据表增加租户标识以及在应用程序中增加表名处理逻辑,适用于单个租户数据量大,但是并发不高的系统
  3. 数据库级别:每个租户使用独立的数据库来存储数据,隔离性最高,但在应用程序中就需要管理多个数据源,增加了管理的复杂性。只有单个租户数据量大且并发高才需要考虑这种隔离方式

之前公司的产品是一个多租户的SAAS平台,是一个面向企业办公的平台,每个企业其实就相当于一个租户。实际使用中采用可 数据行+数据表 混合的数据隔离方案,大多数业务场景中是数据行级别,即所有的数据都在同一张表下,用租户ID来区分。少部分业务场景则是数据表级别,每个租户都有自己的数据表,表名使用租户ID做后缀区分。

数据行

基于绝大多数没有什么并发量和数据量的前提,使用数据行隔离级别就足够了,方案简单易用。

以之前公司的产品作为例子,使用的就是数据行隔离级别。

系统中的租户其实就是企业,在每张数据表中都设计一个企业ID(company_id),不同企业的数据通过企业ID来区分。

在业务操作时都要带上企业ID处理,比如查询时带上企业ID过滤条件,使得查询只查出该企业下的数据;保存数据时带上企业ID,将企业ID保存到表中,标识该行数据是这个企业的,以便查询时过滤。

数据表

采用数据表级别的隔离方案,一般来说,有两个原因。

  1. 业务场景
  2. 数据量大

同样以之前公司的产品作为例子,少部分业务场景就是用了数据表级别的隔离方案。

基于业务场景

公司的产品是面向企业的,每个企业都能基于平台去设计自己的企业应用,实现自己自定义的业务逻辑。简单来说,平台上能注册多个企业,企业间数据互相隔离,每个企业又能够设计多个应用,每个应用的数据也是相互隔离的。

这种业务场景下,针对企业下每个应用的数据隔离,如果还采用数据行隔离的方案,那么只使用企业ID一个字段是区分不了每个应用的数据的,还需要加上应用ID才能够区分;而且由于存在多层的嵌套关系(一个平台注册多个企业,一个企业又可以设计多个应用),显得一张表下储存的数据种类很臃肿。

以上这种场景,可以使用数据表级别隔离方案来优化,每个企业下的应用使用不同的表来存储,表使用企业ID后缀来做区分,表中的数据再通过数据行隔离的方式,通过应用ID(app_id)来区分同一个企业下的不同应用。

这样做的好处就是数据之间的隔离关系显得很清晰,通过表名就能直接了解到数据之间隔离关系。但是个人感觉这种方式是不必要的,从功能实现上来说,直接用数据行隔离和用数据表隔离其实都能够实现,甚至数据行隔离实现还比较简单,使用数据表隔离还需要自己处理表名的逻辑。

基于数据量

基于某些业务场景采用数据表隔离是不必要的,但如果是单个租户数据量大的情况下,那么使用数据表隔离就是必要的了。

公司的产品是面向办公的,每个企业都可以设计自己的表单,表单是办公产品的核心功能,它的数据量是相对较大的。而数据量大的表就会存在查询性能下降等问题,针对数据量大的问题,其实就是使用分表的思路来解决。

在多租户系统的设计中,预先估计了某些表的数据量会比较大,便可以直接提前分表,也就是直接使用数据表隔离级别。在上面的场景中,根据企业ID来进行分表,将数据分散到多个表下,解决单表数据量过大的问题。

数据库

在MySQL中,其实database和schema是没有区别的,但是在PostgreSQL里,database和schema则是有区别的,一个database下有多个schema。

这里的数据库隔离级别,包含了不同的database,也包含了同一个database,不同的schema这种情况。因为在实际使用中, 都需要动态切换数据源,所以将以上两种情况放在一起讨论。

虽然在实际接触的系统中没有使用过这种隔离级别,但是学习最重要的就是做到举一反三,所以这里也写一些数据库隔离级别的实现思路。

数据源表

一般系统都是固定的数据库,所以数据库连接信息都是直接放在项目配置文件中。而多租户系统使用数据库隔离方式,则需要实现数据源切换,就得设计一张表来存储数据库的连接信息

相关表字段如下

  • id 主键id
  • tenent_id 租户id
  • url 数据库url
  • username 用户名
  • password 密码
  • driver 数据库驱动
  • schema 视图

动态数据源

有了数据源表,那么在应用程序中就需要实现动态数据源了,在运行中根据不同的租户ID来获取对应的数据源元信息,构造数据源,放入本地缓存中,并且将这个数据源加入到动态数据中,以便在运行时切换数据源。

具体到Spring框架中,就是使用 切面/拦截器 + AbstractRoutingDataSource + ThreadLocal

使用切面(AOP)或者 拦截器(Interceptor)拦截请求,提取当前请求的租户ID,如果缓存中不存在该租户数据源,则查询数据源表,构造数据源,并加入到动态数据源中

动态数据源再根据租户ID决定运行时的数据源

动态数据源相关的使用可以参考以下:

Spring Boot 动态数据源-CSDN博客文章浏览阅读616次,点赞11次,收藏24次。大多数系统中,都需要数据库来持久化数据,在大多数情况下,一个系统只需要配置一个数据源便能够完成所有业务的查询,保存操作。也存在一个系统需要多个数据源的情况,不同的数据源对应不同的业务操作,这种场景下配置多个数据源,并且在代码中维护多套dao层就可以了。还存在一种业务场景,所有的业务操作都是一样的,只有操作的数据源的不同,如果用多套dao层来实现,由于业务操作都一样,会出现多块一模一样的代码,这样的冗余代码是我们不希望看到,不利于维护。这种业务场景就很适合用动态数据源来实现。https://blog.csdn.net/typeracer/article/details/140814168

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/391513.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[云原生]三、Kubernetes(1.18)

主要内容: 1、kubernetes 简介 2、kubernetes 集群搭建  方式搭建  二进制方式搭建 3、 kubeadm kubernetes 核心技术  YAML 文件详解  kubectl 命令工具  Pod  Label  Controller 控制器 …

职业教育大数据实验实训室建设应用案例

大数据作为一种重要的信息技术,对各行各业产生了深远的影响。职业教育作为培养应用型人才的摇篮,建设大数据实验实训室,对于提高学生的数据分析能力和解决实际问题的能力具有重要意义。唯众作为一家专注于教育技术领域的企业,凭借…

从零开始:MySQL安装与配置完全指南

前言 哇,终于进入到令人激动的MySQL环节了 它可以说是你编程生涯中的最佳朋友,因为它总是能存储你的数据,从不说:“我忘记了你的信 息”。而且,它是免费的,不像一些昂贵的数据库,它从不让你的…

量产部落SM2258XT开卡软件,SM2258XT主控128G SSD固态卡死修复

故障现象:连接此固态硬盘后电脑就会卡死,拔掉重新连接概率性显示盘符,显示了之后也不能正常操作,一点击打开,电脑就立马卡死。 解决过程:下载了很多款量产工具,都不能开卡成功,点击…

Elasticsearch 未授权访问漏洞

Elasticsearch 未授权访问漏洞 ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索…

iAppv3无白银会员使用SDK

前言 一个实用小技巧分享给大家。 工具 iapp:百度或点我获取 Mt管理器:百度或点我获取 教程 1.移出“项目路径/apk/lib/”内的全部文件 2.在iapp内测试打包,打包完成后直接返回,不要安装 3.在mt管理器里面点击“项目路径/b…

【课程总结】Day18:Seq2Seq的深入了解

前言 在上一章【课程总结】Day17(下):初始Seq2Seq模型中,我们初步了解了Seq2Seq模型的基本情况及代码运行效果,本章内容将深入了解Seq2Seq模型的代码,梳理代码的框架图、各部分组成部分以及运行流程。 框…

【大模型系列】LanguageBind(ICLR2024.01)

Paper:https://arxiv.org/abs/2310.01852Github:https://github.com/PKU-YuanGroup/LanguageBindHuggingface:https://huggingface.co/spaces/LanguageBind/LanguageBindAuthor:Bin Zhu et al. 北大袁粒团队 文章目录 1 LanguageB…

入门mem0.NET

入门mem0.NET 安装包 如果你的项目使用了EntityFrameworkCore,那么你可以跟随这个教程走 <ItemGroup><PackageReference Include"mem0.NET" Version"0.1.7" /><PackageReference Include"mem0.NET.Qdrant" Version"0.1.7…

软件测试需要具备的基础知识【功能测试】---前端知识(一)

​ ​ 您好&#xff0c;我是程序员小羊&#xff01; 前言 为了更好的学习软件测试的相关技能&#xff0c;需要具备一定的基础知识。需要学习的基础知识包括&#xff1a; 1、计算机基础 2、前端知识 3、后端知识 4、软件测试理论 后期分四篇文章进行编写&#xff0c;这是第二篇 …

【精选】通信与感知(ISAC)必读好文

微信公众号&#xff1a;EW Frontier 个人博客&#xff1a;106.54.201.174 QQ交流群&#xff1a;949444104 简介 通信与感知&#xff08;ISAC&#xff09;也被称为联合雷达通信 (JRC) / 联合通信和雷达传感 (JCAS) / 双功能雷达通信 (DFRC) 定义&#xff1a;将传感和通信系统集…

记录一次学习过程(msf、cs的使用、横向渗透等等)

目录 用python搭建一个简单的web服务器 代码解释 MSF msfvenom 功能 用途 查看payloads列表 msfconsole 功能 用途 msfvenom和msfconsole配合使用 来个例子 msf会话中用到的一些命令 在windows中net user用法 列出所有用户账户 显示单个用户账户信息 创建用户账…

学python的第一天:PyCharm创建项目

创建项目 打开工具 PyCharm 点击“新建项目” 点击“创建” 环境 系统会创建虚拟环境&#xff0c;稍等 初始设置 创建完成后会进入main.py文件 性能 可以看到 右下角提示我们增强性能&#xff0c;点“自动” 会获取到管理员权限 完成后会提示完成

【数据结构】栈和队列(c语言实现)(附源码)

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;数据结构 目录 一、栈 1.栈的概念与结构 2.栈的实现 2.1 栈的结构定义 2.2 方法的声明 2.3 方法的实现 2.3.1 初始化 2.3.2 销毁 2.3.3 判空 2.3.4 压…

常见CMS漏洞(WordPress、DeDeCMS、ASPCMS、PHPMyadmin、Pageadmin)

目录 一&#xff1a;WordPress 步骤一:进入Vulhub靶场并执行以下命令开启靶场;在浏览器中访问并安装好子... 步骤二:思路是修改其WP的模板写入一句话木马后门并访问其文件即可GetShel;登陆WP后点击【外观】--》【编辑】 --》 404.php 步骤三:访问以下连接即可获取WebShel...…

用VBA在Word中随机打乱单词表,进行分列

一、效果展示&#xff08;以下是三次随机打乱的结果&#xff09; 二、代码 Sub 随机分单词到后面的单元格()Dim C1 As CellDim str, str1, aDim shuffledArray() As VariantSet C1 Selection.Range.Tables(1).Cell(1, 1)str C1.Range.textstr mid(str, 3, Len(str) - 4)str…

ADC的介绍和工作原理

一&#xff0c;什么是ADC&#xff1f; Analog-to-Digital Converter&#xff0c;指模拟/数字转换器 什么是ADC&#xff1a; ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量&#xff0c;建立模拟电路到数字电路的桥梁 SUCH AS: 12 位 ADC 是一种逐次逼近…

C# Solidworks二次开发------设置按键打开模型查询

一、代码 public void Open_File(string FileNmae) {Process.Start("explorer.exe", FileNmae); }Open_File("路径"); 二、内容 这个代码很简单&#xff0c;我使用其主要的作用是设置一个按键&#xff0c;可以快速的查看我们已生成的三维模型&#xff0…

JS使用 navigator.clipboard 操作剪切板

注意&#xff1a;需要在安全域下才能够使用&#xff0c;比如&#xff1a;https 协议的地址、127.0.0.1、localhost safari浏览器需要打开配置&#xff0c;在地址栏输入 about:config&#xff0c;搜索 clipboard&#xff0c;将 asyncClipboard 由 false 改为 true&#xff0c;然…

C语言初阶(11)

1.结构体定义 结构体就是一群数据类型的集合体。这些数据类型被称为成员变量。结构的成员可以是标量、数组、指针&#xff0c;甚至是其他结构体。 2.结构体的声明和结构体变量命名与初始化 结构体声明由以下结构组成 struct stu {char name[12];int age; }; 结构体命名有两…