多租户:每个租户都有单独的数据库

2024-03-20

我们正在开发一个多租户应用程序。在架构方面,我们设计了共享中间层用于业务逻辑,每个租户一个数据库用于数据持久化。也就是说,业务层将为每个租户与数据库服务器建立一组连接(连接池)。这意味着应用程序为每个租户维护单独的连接池。如果我们预计大约有 5000 个租户,那么该解决方案需要高资源利用率(每个租户的应用程序服务器和数据库服务器之间的连接),这会导致性能问题。

我们通过保留公共连接池解决了这个问题。为了跨不同数据库维护单个连接池,我们创建了一个名为“App-master”的新数据库。现在,我们总是先连接到“App-master”数据库,然后将数据库更改为租户特定数据库。这解决了我们的连接池问题。

该解决方案与本地数据库服务器完美配合。但它不适用于 Azure Sql,因为它不支持更改数据库。

提前感谢建议如何维护连接池或更好的方法/最佳实践来处理这种多租户场景。


我之前在具有单独数据库的多个租赁方案中见过这个问题。有两个重叠的问题;每个租户的 Web 服务器数量以及租户总数。第一个是更大的问题 - 如果您通过 ADO.net 连接池缓存数据库连接,那么任何特定客户连接进入与其数据库有开放连接的 Web 服务器的可能性与您的 Web 服务器数量成反比。有。扩展得越多,任何给定客户就越会注意到每次调用(而不是初始登录)延迟,因为 Web 服务器代表他们与数据库进行初始连接。对非粘性、高度扩展的 Web 服务器层进行的每次调用找到可重用的现有开放数据库连接的可能性将会降低。

第二个问题只是池中存在如此多的连接,以及这可能会造成内存压力或性能不佳的问题之一。

您可以通过建立有限数量的数据库应用程序服务器(简单的 WCF 端点)来“解决”第一个问题,这些服务器代表您的 Web 服务器执行数据库通信。每个 WCF 数据库应用程序服务器都提供已知的客户连接池(东部区域转到服务器 A,西部区域转到服务器 B),这意味着任何给定请求的连接池命中的可能性非常高。这还允许您单独扩展对数据库的访问以访问 HTML 渲染 Web 服务器(数据库是您最关键的性能瓶颈,因此这可能不是一件坏事)。

第二种解决方案是通过 NLB 路由器使用内容特定路由。这些基于内容路由流量,并允许您按客户分组(西部地区、东部地区等)对 Web 服务器层进行细分,因此每组 Web 服务器的活动连接数量要少得多,获得的可能性相应增加开放且未使用的连接。

这两个问题通常都是缓存问题,作为完全“不粘”的架构横向扩展得越多,任何调用命中缓存数据的可能性就越小 - 无论是缓存的数据库连接还是读取缓存的数据。管理用户连接以允许缓存命中的最大可能性对于保持高性能非常有用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

多租户:每个租户都有单独的数据库 的相关文章

  • 如何捕获未发送到 stdout 的命令行文本?

    我在项目中使用 LAME 命令行 mp3 编码器 我希望能够看到某人正在使用什么版本 如果我只执行 LAME exe 而不带参数 我会得到 例如 C LAME gt LAME exe LAME 32 bits version 3 98 2
  • GetType() 在 Type 实例上返回什么?

    我在一些调试过程中遇到了这段代码 private bool HasBaseType Type type out Type baseType Type originalType type GetType baseType GetBaseTyp
  • 使用 Adal 代表用户访问 Azure KeyVault

    以下是控制台应用程序和 ClientID RedirectUri 来自 azure Active Directory 中创建的本机应用程序 var authContext new AuthenticationContext string F
  • IdentityServer 4 对它的工作原理感到困惑

    我阅读和观看了很多有关 Identity Server 4 的内容 但我仍然对它有点困惑 因为似乎有很多移动部件 我现在明白这是一个单独的项目 它处理用户身份验证 我仍然不明白的是用户如何注册它 谁存储用户名 密码 我打算进行此设置 Rea
  • 查找进程的完整路径

    我已经编写了 C 控制台应用程序 当我启动应用程序时 不使用cmd 我可以看到它列在任务管理器的进程列表中 现在我需要编写另一个应用程序 在其中我需要查找以前的应用程序是否正在运行 我知道应用程序名称和路径 所以我已将管理对象搜索器查询写入
  • 如何判断计算机是否已重新启动?

    我曾经使用过一个命令行 SMTP 邮件程序 作为试用版的限制 它允许您在每个 Windows 会话中最多接收 10 封电子邮件 如果您重新启动计算机 您可能还会收到 10 个以上 我认为这种共享软件破坏非常巧妙 我想在我的应用程序中复制它
  • 如何使用 Castle Windsor 将对象注入到 WCF IErrorHandler 实现中?

    我正在使用 WCF 开发一组服务 该应用程序正在使用 Castle Windsor 进行依赖注入 我添加了一个IErrorHandler通过属性添加到服务的实现 到目前为止一切正常 这IErrorHandler对象 一个名为FaultHan
  • 函数参数的默认参数是否被视为该参数的初始值设定项?

    假设我有这样的函数声明 static const int R 0 static const int I 0 void f const int r R void g int i I 根据 dcl fct default 1 如果在参数声明中指
  • 为什么在 WebApi 上下文中在 using 块中使用 HttpClient 是错误的?

    那么 问题是为什么在 using 块中使用 HttpClient 是错误的 但在 WebApi 上下文中呢 我一直在读这篇文章不要阻止异步代码 https blog stephencleary com 2012 07 dont block
  • 查看 NuGet 包依赖关系层次结构

    有没有一种方法 文本或图形 来查看 NuGet 包之间的依赖关系层次结构 如果您使用的是新的 csproj 您可以在此处获取所有依赖项 在项目构建后 项目目录 obj project assets json
  • 在Linux中,找不到框架“.NETFramework,Version=v4.5”的参考程序集

    我已经设置了 Visual studio 来在我的 Ubuntu 机器上编译 C 代码 我将工作区 我的代码加载到 VS 我可以看到以下错误 The reference assemblies for framework NETFramewo
  • 启动时的 Excel 加载项

    我正在使用 Visual C 创建 Microsoft Excel 的加载项 当我第一次创建解决方案时 它包含一个名为 ThisAddIn Startup 的函数 我在这个函数中添加了以下代码 private void ThisAddIn
  • 使用valgrind进行GDB远程调试

    如果我使用远程调试gdb我连接到gdbserver using target remote host 2345 如果我使用 valgrind 和 gdb 调试内存错误 以中断无效内存访问 我会使用 target remote vgdb 启动
  • 如何在 Qt 应用程序中通过终端命令运行分离的应用程序?

    我想使用命令 cd opencv opencv 3 0 0 alpha samples cpp cpp example facedetect lena jpg 在 Qt 应用程序中按钮的 clicked 方法上运行 OpenCV 示例代码
  • 为什么这个二维指针表示法有效,而另一个则无效[重复]

    这个问题在这里已经有答案了 这里我编写了一段代码来打印 3x3 矩阵的对角线值之和 这里我必须将矩阵传递给函数 矩阵被传递给指针数组 代码可以工作 但问题是我必须编写参数的方式如下 int mat 3 以下导致程序崩溃 int mat 3
  • C++ int 前面加 0 会改变整个值

    我有一个非常奇怪的问题 如果我像这样声明一个 int int time 0110 然后将其显示到控制台返回的值为72 但是当我删除前面的 0 时int time 110 然后控制台显示110正如预期的那样 我想知道两件事 首先 为什么它在
  • 等待 IAsyncResult 函数直至完成

    我需要创建等待 IAsyncResult 方法完成的机制 我怎样才能做到这一点 IAsyncResult result contactGroupServices BeginDeleteContact contactToRemove Uri
  • 检测到严重错误 c0000374 - C++ dll 将已分配内存的指针返回到 C#

    我有一个 c dll 它为我的主 c 应用程序提供一些功能 在这里 我尝试读取一个文件 将其加载到内存 然后返回一些信息 例如加载数据的指针和内存块的计数到 c Dll 成功将文件读取到内存 但在返回主应用程序时 程序由于堆损坏而崩溃 检测
  • Unity:通过拦截将两个接口注册为一个单例

    我有一个实现两个接口的类 我想对该类的方法应用拦截 我正在遵循中的建议Unity 将两个接口注册为一个单例 https stackoverflow com questions 1394650 unity register two inter
  • OpenCV SIFT 描述符关键点半径

    我正在深入研究OpenCV的SIFT描述符提取的实现 https github com Itseez opencv blob master modules nonfree src sift cpp 我发现了一些令人费解的代码来获取兴趣点邻域

随机推荐