多租数据架构设计

多租数据架构设计

原文地址:https://web.archive.org/web/20110311185417/http://msdn.microsoft.com/en-us/library/aa479086.aspx#mlttntda_topic1

目录: 简介 多租数据中心设计的三种方案 方案选择 实现架构 结论 反馈

简介

信任或缺乏信任是阻碍采用软件即服务(SaaS)的首要因素。可以说,数据是任何业务数据中最重要的资产 - 有关产品,客户,员工,供应商等的数据。当然,数据是SaaS的核心。 SaaS应用程序为客户提供集中的,基于网络的数据访问,与使用本地安装的应用程序时相比,开销更少。但是,为了利用SaaS的优势,组织必须放弃对其自身数据的控制,信任SaaS供应商以确保其安全并远离窥探。

为了赢得这种信任,未来SaaS架构师的最高优先事项之一就是创建一个既健壮又安全的SaaS数据架构,用来满足那些担心将重要业务数据交给第三方的租户或客户,同时需要保证数据的管理和维护是高效和低成本的。

在本文中,我们将研究隔离数据和共享数据之间的相关性以及不同点,分别介绍三种不同的架构设计方式;接下来,我们将探讨一下如何在这三种架构之间做出对应不同使用场景时如何选择,最后,我们将介绍如何确保数据的安全性,数据的可扩展性和架构的可扩展性。

三种多租数据管理架构

共享数据和隔离数据之间的区别不是互斥的。 相反,它更像是一个连续体,在两个极端之间可能存在许多变化。 数据体系结构是SaaS应用程序的最佳隔离程度可能因技术和业务考虑而显着变化的领域。 在设计架构以应对特定挑战时,经验丰富的数据架构师习惯于考虑广泛的选择,而SaaS当然也不例外。 我们将研究三种广泛的方法,每种方法都位于隔离和共享之间的连续统一的不同位置。

数据库隔离

将租户数据存储在单独的数据库中是最简单的数据隔离方法。 图1.此方法为每个租户使用不同的数据库

计算资源和应用程序代码通常在服务器上的所有租户之间共享,但每个租户都有自己的数据集,这些数据在逻辑上与其他租户的数据隔离。元数据将每个数据库与正确的租户相关联,并且数据库安全性可防止任何租户意外或恶意访问其他租户的数据。

为每个租户提供自己的数据库,可以轻松扩展应用程序的数据模型(稍后讨论)以满足租户的个性化需求,并在发生故障时从备份中恢复租户的数据是一个相对简单的过程。不幸的是,这种方法往往会导致维护设备和备份租户数据的成本增加。硬件成本也高于其他方法,因为可以容纳在给定数据库服务器上的租户数量受服务器可以支持的数据库数量的限制。 (当没有活动连接时,使用autoclose从内存中卸载数据库可以通过增加每个服务器可以支持的数据库数量来使应用程序更具可伸缩性。)

将租户数据分成单独的数据库是“高级”方法,相对较高的硬件和维护要求和成本使其适合愿意为额外的安全性和可定制性支付额外费用的客户。例如,银行或医疗记录管理等领域的客户通常具有非常强大的数据隔离要求,甚至可能不会考虑不为每个租户提供其自己的个人数据库的应用程序。

共享数据库,不同的Schema

另一种方法涉及在同一数据库中容纳多个租户,每个租户都有自己的一组表,这些表被分组到专为租户创建的模式中。 图2.在此方法中,每个租户在公共数据库中都有自己独立的表集

当客户首次订购服务时,供应子系统为租户创建一组离散的表,并将其与租户自己的架构相关联。 您可以使用SQL CREATE命令创建架构并授权用户帐户访问它。 例如,在Microsoft SQL Server 2005中:

CREATE SCHEMA ContosoSchema AUTHORIZATION Contoso  

然后,应用程序可以使用SchemaName.TableName约定在租户的模式中创建和访问表:

CREATE TABLE ContosoSchema.Resumes (EmployeeID int identity primary key,  
   Resume nvarchar(MAX))

租户帐户可以通过仅指定表名来访问其默认架构中的表,而不是使用SchemaName.TableName约定。 这样,可以为所有租户创建一组SQL语句,每个租户都可以使用这些语句来访问自己的数据:

SELECT * FROM Resumes  

与隔离方法一样,单独模式方法相对容易实现,租户可以像使用单独数据库方法一样轻松扩展数据模型。 (表是从标准默认集创建的,但是一旦创建它们就不再需要符合默认集,并且租户可以根据需要添加或修改列甚至表。)此方法提供适度的逻辑数据隔离对于注重安全的租户而言,虽然不如完全隔离的系统那样多,但每个数据库服务器可以支持更多的租户。

单独模式方法的一个显着缺点是租户数据在发生故障时更难恢复。如果每个租户都有自己的数据库,则还原单个租户的数据意味着只需从最新的备份中还原数据库。使用单独的模式应用程序,还原整个数据库意味着使用备份数据覆盖同一数据库上每个租户的数据,无论每个租户是否经历过任何损失。因此,要恢复单个客户的数据,数据库管理员可能必须将数据库还原到临时服务器,然后将客户的表导入生产服务器 - 这是一项复杂且可能非常耗时的任务。

单独的模式方法适用于使用相对较少数量的数据库表的应用程序,每个租户大约100个表或更少。与单独数据库方法相比,这种方法通常可以容纳每台服务器更多的租户,因此只要您的客户接受其数据与其他租户的数据位于同一位置,您就可以以较低的成本提供应用程序。

共享数据库,共享Schema

第三种方法涉及使用相同的数据库和同一组表来托管多个租户的数据。 给定的表可以包括以任何顺序存储的多个租户的记录; 租户ID列将每条记录与相应的租户相关联。 图3.在此方法中,所有租户共享同一组表,租户ID将每个租户与其拥有的行相关联

在这里解释的三种方法中,共享模式方法具有最低的硬件和备份成本,因为它允许您为每个数据库服务器提供最大数量的租户。但是,由于多个租户共享相同的数据库表,因此这种方法可能会在安全领域产生额外的开发工作,以确保租户永远无法访问其他租户的数据,即使出现意外错误或攻击。

恢复租户数据的过程类似于共享模式方法的过程,另外的复杂性是必须删除生产数据库中的各个行,然后从临时数据库重新插入。如果受影响的表中存在大量行,则会导致数据库所服务的所有租户的性能明显下降。

当应用程序能够为少量服务器的大量租户提供服务非常重要时,共享模式方法是合适的,并且潜在客户愿意放弃数据隔离以换取此方法可能实现的较低成本。

选择方法

上述三种方法中的每一种都提供了自己的一系列利益和权衡,使其成为在某些情况下而非在其他情况下遵循的适当模型,这由许多业务和技术考虑因素决定。 下面列出了其中一些注意事项。

成本角度考虑

针对共享方法优化的应用程序往往需要比使用更加孤立的方法设计的应用程序更大的开发工作量(因为开发共享架构的相对复杂性),导致更高的初始成本。 但是,由于每台服务器可以支持更多租户,因此其持续运营成本往往较低。 图4.假设的一对SaaS应用程序的成本随时间变化; 一个使用更孤立的方法,而另一个使用更共享的方法

您的开发工作可能受到业务和经济因素的限制,这可能会影响您选择的方法。 共享模式方法最终可以为您节省资金,但它确实需要更大的初始开发工作才能开始产生收入。 如果您无法为构建共享模式应用程序所需的大小的开发工作提供资金,或者如果您需要比大规模开发工作允许的更快地将应用程序推向市场,则可能必须考虑更加孤立做法。

安全角度考虑

由于您的应用程序将存储敏感的租户数据,因此潜在客户对安全性有很高的期望,您的服务级别协议(SLA)需要提供强大的数据安全保障。 一种常见的误解认为只有物理隔离才能提供适当的安全级别。 事实上,使用共享方法存储的数据也可以提供强大的数据安全性,但需要使用更复杂的设计模式。

租户本身考虑

您希望服务的租户的数量,性质和需求都会以不同的方式影响您的数据架构决策。 以下某些问题可能会使您偏向于更加孤立的方法,而其他问题则可能会使您偏向更为共享的方法。

  • 您期望有多少潜在租户? 您可能无法估计有权使用的预期用途,但请考虑数量级:您是否正在为数百个租户构建应用程序?成千上万的? 成千上万? 更多? 您希望租户基数越大,您就越有可能考虑采用更加共享的方法。
  • 您希望平均租户的数据占用多少存储空间? 如果您希望部分或全部租户存储大量数据,则单独数据库方法可能是最佳方法。 (实际上,数据存储要求可能会迫使您采用单独的数据库模型。如果是这样,从一开始就设计应用程序要比以后转移到单独的数据库方法要容易得多。)
  • 您希望普通租户支持多少并发最终用户? 数字越大,更孤立的方法越适合满足最终用户的要求。
  • 您是否希望提供任何每租户增值服务,例如每租户备份和恢复功能? 通过更加孤立的方法更容易提供此类服务。 图5.与租户相关的因素以及它们如何影响“隔离与共享”数据架构决策

法律合规性考虑

公司,组织和政府通常受制于可能影响其安全性并记录存储需求的监管法律。 调查您的潜在客户在您期望运营的市场中占据的监管环境,并确定他们是否提出任何会影响您决策的考虑因素。

技术成熟度考虑

设计单实例,多租户架构仍然是一项非常新的技能,因此很难获得主题专业知识。 如果您的架构师和支持人员在构建SaaS应用程序方面没有丰富的经验,他们将需要获得必要的知识,或者您将需要雇用已经拥有SaaS应用程序的人员。 在某些情况下,更加孤立的方法可能允许您的员工利用其现有的传统软件开发知识,而不是更多的共享方法。

多租数据架构实现

本文的其余部分详细介绍了一些可以帮助您规划和构建SaaS应用程序的模式。正如我们在介绍性文章中所讨论的那样,精心设计的SaaS应用程序具有三个特点:可扩展性,可配置性和多租户效率。下表列出了适用于这三种方法中每种方法的模式,分为代表这三种特性的部分。

在共享环境中优化多租户效率不得损害保护数据访问的安全级别。下面列出的安全模式演示了如何通过权限,SQL视图和加密等机制设计具有“虚拟隔离”的应用程序。

可配置性允许SaaS租户改变应用程序的显示和行为方式,而无需为每个租户分别设置单独的应用程序实例。可扩展性模式描述了可以实现数据模型的可能方式,租户可以单独扩展和配置以满足其需求。

您为SaaS应用程序的数据体系结构选择的方法将影响您可用于扩展它以适应更多租户或更重用的选项。可伸缩性模式解决了扩展共享数据库和专用数据库所带来的不同挑战。

表1. SaaS应用程序的适当模式 | 方案 | 安全范式| 可扩展范式 | 可伸展范式 | | ------------ | --- | ------------------------------- |------------------------------- | | 独立数据库 |
可信任的数据库连接
安全的数据库表
租户数据加密 | 扩展表列|单租户横向扩展 | 共享数据库,独立Schema|
可信任的数据库连接
安全的数据库表
租户数据加密 |扩展表列|基于租户的水平分区 | 共享数据库,共享Schema|
可信任的数据库连接
租户数据视图过滤
租户数据加密 |预分配数据字段
数据键值对|基于租户的水平分区

安全范式

为应用程序的每个方面构建足够的安全性是任何SaaS架构师的首要任务。 推广软件即服务基本上意味着要求潜在客户放弃对其业务数据的某些控制。 根据应用程序的不同,这可能包括有关财务,商业机密,员工数据等的极其敏感的信息。 安全的SaaS应用程序是一种提供深度防御的应用程序,它使用多个防御级别相互补充,以在不同情况下以不同方式提供针对内部和外部威胁的数据保护。

将安全性构建到SaaS应用程序意味着在不同级别查看应用程序并考虑风险所在以及如何解决这些风险。 本节中讨论的安全模式依赖于三种基础模式,以在适当的位置提供正确的安全性:

  • 过滤:使用租户和充当筛子的数据源之间的中间层,使租户看起来好像其数据是数据库中的唯一数据。
  • 权限:使用访问控制列表(ACL)确定谁可以访问应用程序中的数据以及可以使用它执行的操作。
  • 加密:模糊每个租户的关键数据,以便未经授权的各方即使拥有它也无法访问。

在阅读本节的其余部分时,请牢记这些模式。

可信数据库连接

在多层应用程序环境中,应用程序架构师传统上使用两种方法来保护对存储在数据库中的数据的访问:模拟和受信任的子系统帐户。

使用模拟访问方法,数据库设置为允许各个用户访问不同的表,视图,查询,存储过程和其他数据库对象。 当最终用户执行直接或间接需要调用数据库的操作时,应用程序将自己作为该用户呈现给数据库,从字面上模仿用户以访问数据库。 (在技术方面,应用程序使用用户的安全上下文)。 可以使用诸如Kerberos委派之类的机制来允许应用程序进程代表用户连接到数据库。 图6.应用程序使用模拟连接到数据库 使用受信任的子系统访问方法,应用程序始终使用自己的应用程序进程标识连接到数据库,而不依赖于用户的身份; 然后,服务器授予应用程序对应用程序可以读取或操作的数据库对象的访问权限。 必须在应用程序本身内实现任何其他安全性,以防止各个最终用户访问不应向其公开的任何数据库对象。 这种方法使安全管理更容易,无需基于每个用户配置对数据库对象的访问,但这意味着放弃为单个用户保护数据库对象的能力。 图7.应用程序作为受信任的子系统连接到数据库 在SaaS应用程序中,“用户”的概念比传统应用程序稍微复杂一些,因为租户和最终用户之间存在区别。 租户是一个使用该应用程序访问其自己的数据存储的组织,该数据存储在逻辑上与属于任何其他租户的数据存储隔离。 每个租户授予一个或多个最终用户访问应用程序的权限,允许他们使用租户控制的最终用户帐户访问租户数据的某些部分。

在此方案中,您可以使用混合方法进行数据访问,该方法结合了模拟和受信任子系统访问方法的各个方面。 这使您可以利用数据库服务器的本机安全机制来强制实施租户数据的最大逻辑隔离,而无需创建不可行的复杂安全模型。 图8. SaaS应用程序使用模拟和受信任子系统方法的组合连接到数据库

此方法涉及为每个租户创建数据库访问帐户,并使用ACL授予每个租户帐户访问允许租户使用的数据库对象的权限。当最终用户执行直接或间接需要调用数据库的操作时,应用程序将使用与租户帐户关联的凭据,而不是与最终用户关联的凭据。 (应用程序获取正确凭据的一种方法是通过模拟,与Kerberos等凭证系统一起使用。第二种方法是使用安全令牌服务,返回为租户建立的实际加密登录凭据集,即然后,应用程序进程可以提交到数据库。)数据库服务器不区分源自与同一租户关联的不同最终用户的请求,并授予所有此类请求访问租户数据的权限。在应用程序本身中,安全代码阻止最终用户接收和修改他们无权访问的任何数据。

例如,考虑客户关系管理(CRM)应用程序的最终用户,该应用程序执行查询数据库以查找与特定字符串匹配的客户记录的操作。应用程序使用租户的安全上下文将查询提交到数据库,因此查询仅检索允许租户访问的表中的匹配行,而不是返回数据库中的所有匹配记录。到目前为止,这么好 但是假设最终用户的角色只允许她访问位于特定地理区域内的客户的记录应用程序必须拦截查询结果,并且只向用户显示她有权使用的记录。看到。

安全加固数据库表

要在表级别上保护数据库,请使用SQL的GRANT命令授予租户用户帐户对表或其他数据库对象的访问权限:

GRANT SELECT, UPDATE, INSERT, DELETE ON [TableName] FOR [UserName]  

这会将用户帐户添加到表的ACL中。 如果您使用前面讨论的混合方法进行数据库访问,其中最终用户与其各自租户的安全上下文相关联,则只需在租户配置过程中执行一次; 租户创建的任何最终用户帐户都可以访问该表。

此模式适用于单独数据库和单独模式方法。 在单独数据库方法中,您可以通过简单地将数据库范围级别的访问限制到与该数据库关联的租户来隔离数据,尽管您也可以在表级别使用此模式来创建另一层安全性。

租户视图过滤器

SQL视图可用于授予单个租户访问给定表中某些行的权限,同时防止它们访问其他行。

在SQL中,视图是由SELECT查询的结果定义的虚拟表。 然后可以查询生成的视图并将其用于存储过程,就好像它是一个实际的数据库表一样。 例如,以下SQL语句创建一个名为Employees的表的视图,该表已被过滤,以便只显示属于单个租户的行:

CREATE VIEW TenantEmployees AS  
SELECT * FROM Employees WHERE TenantID = SUSER_SID()  

此语句获取访问数据库的用户帐户的安全标识符(SID)(您可以回忆,它是属于租户的帐户,而不是最终用户),并使用它来确定视图中应包含哪些行。 (该示例假定唯一租户ID号与租户的SID相同。如果不是这种情况,则需要一个或多个额外步骤将每个租户与正确的行相关联。)每个租户的数据访问帐户将是 授予使用TenantEmployees视图的权限,但未授予Employees源表本身的权限。 您可以构建查询和共享过程以利用视图,即使在多租户数据库中,也可以为租户提供数据隔离的外观。

此模式比安全数据库表模式稍微复杂一些,但它是在共享模式应用程序中保护租户数据的适当方法,其中多个租户共享同一组表。

租户数据加密

进一步保护租户数据的一种方法是在数据库中对其进行加密,这样即使数据落入坏人手中,数据也将保持安全。

加密方法分为对称或非对称。在对称加密中,生成用于加密和解密数据的密钥。用对称密钥加密的数据可以用相同的密钥解密。在非对称加密(也称为公钥加密)中,使用两个密钥,指定公钥和私钥。使用给定公钥加密的数据只能使用相应的私钥解密,反之亦然。通常,公钥被分发给有兴趣与密钥持有者通信的任何和所有各方,而私钥是安全的。例如,如果Alice希望向Bob发送加密消息,则她通过一些商定的手段获取Bob的公钥,并使用它来加密消息。产生的加密消息或密文只能由拥有Bob私钥的人解密(实际上,这应该只是Bob)。这样,Bob就不必与Alice分享他的私钥。为了使用对称加密向Bob发送消息,Alice必须单独发送对称密钥 - 这会冒着在传输过程中密钥可能被第三方拦截的风险。

公钥加密比对称加密需要更多的计算能力;强密钥对可以花费数百甚至数千倍的时间来加密和解密数据,作为类似质量的对称密钥。对于每个存储数据都经过加密的SaaS应用程序,由此产生的处理开销可能会使公钥加密作为整体解决方案不可行。更好的方法是使用结合两种系统优点的密钥包装系统。

通过这种方法,作为供应过程的一部分,为每个租户创建三个密钥:对称密钥和由公钥和私钥组成的非对称密钥对。更高效的对称密钥用于加密租户的关键数据以进行存储。为了添加另一层安全性,公钥/私钥对用于加密和解密对称密钥,以保证其不受任何潜在的入侵者的影响。

当最终用户登录时,应用程序使用模拟来使用租户的安全上下文访问数据库,该安全上下文授予应用程序进程访问租户私钥的权限。然后,应用程序(当然仍模仿租户)可以使用租户的私钥来解密租户的对称密钥并使用它来读取和写入数据。

这是深度防御原则的另一个例子。租户数据意外或恶意暴露给其他租户 - 这是安全意识SaaS提供商的噩梦场景 - 在多个层面上被阻止。在数据库级别的第一道防线阻止最终用户访问其他租户的私有数据。如果数据库服务器中的错误或病毒导致将错误的行传递给租户,则该行的加密内容将无法访问租户的私钥。

加密的重要性使SaaS应用程序越接近隔离/共享连续体的“共享”端。在涉及高价值数据或隐私问题的情况下,或者当多个租户共享同一组数据库表时,加密尤其重要。

因为您无法索引加密列,所以选择要加密哪些表的哪些列涉及在数据安全性和性能之间进行权衡。在决定加密时,请考虑数据模型中各种数据的用途和敏感性。

可扩展性模式

使数据模型可扩展的一种方法是在希望允许租户扩展的每个表中创建预设数量的自定义字段。 图9.包含预设自定义字段集合的表,标记为C1到C3

在上图中,来自不同客户的记录混合在一个表中; 租户ID字段将每个记录与单个租户相关联。 除了标准字段集之外,还提供了许多自定义字段,每个客户都可以选择使用这些字段的内容以及如何为它们收集数据。

那么数据类型呢? 您可以为您创建的每个自定义字段选择一种通用数据类型,但客户可能会发现此方法不必要地限制 - 如果客户需要三个额外的字符串字段并且您只提供了一个字符串字段,一个整数 字段和一个布尔字段? 提供这种灵活性的一种方法是对每个自定义字段使用字符串数据类型,并使用元数据来跟踪租户希望使用的“真实”数据类型。 图10.网页上的自定义字段,由元数据表中的条目定义

在上面的示例中,租户使用应用程序的可扩展性功能将名为“Originating ZIP Code”的文本框添加到数据输入屏幕,并将文本框映射到名为C1的自定义字段。 在创建文本框时,租户使用验证逻辑(未显示)来要求文本框包含整数。 实现时,此自定义字段由元数据表中的记录定义,该记录包括租户的唯一ID号(1017),租户为该字段选择的标签(“Originating ZIP Code”)以及租户想要的数据类型 用于字段(“int”)。

您可以在单个元数据表中跟踪所有应用程序的自定义字段的字段定义,或者为每个自定义字段使用单独的表; 例如,“C1”表将为使用它的每个租户定义自定义字段C1,“C2”表对自定义字段C2执行相同的操作,依此类推。 图11.将字段定义存储在单个元数据表,顶部和每个自定义字段的单独表中

使用单独表的主要优点是每个特定于字段的表仅包含使用该字段的租户的行,这样可以节省数据库中的空间。 (使用单表方法,每个使用至少一个自定义字段的租户在组合表中获取一行,空字段表示租户未使用的可用自定义字段)。 使用单独表的缺点是它增加了自定义字段操作的复杂性,要求您使用SQL JOIN语句来调查单个租户的所有自定义字段定义。

当最终用户在字段中键入数量并保存记录时,应用程序会在创建或更新数据库中的记录之前将原始邮政编码的值转换为字符串。 每当应用程序检索记录时,它都会检查元数据表以查找要使用的数据类型,并将自定义字段中的值转换回其原始类型。

名称 - 值对

上一节中介绍的Preallocated Fields模式是一种为租户提供扩展和自定义应用程序数据模型的机制的简单方法。 但是,这种方法有一定的局限性。 确定在给定表中提供多少自定义字段涉及进行权衡。 自定义字段太少,租户会受到应用程序的限制和限制; 太多,数据库变得稀疏和浪费,有许多未使用的字段。 在极端情况下,两者都可能发生,一些租户使用自定义字段而其他人要求更多。

避免这些限制的一种方法是允许客户任意扩展数据模型,将自定义数据存储在单独的表中,并使用元数据为每个租户的自定义字段定义标签和数据类型。 图12.扩展表允许每个租户定义任意数量的自定义字段

这里,元数据表存储有关每个租户定义的每个自定义字段的重要信息,包括字段的名称(标签)和数据类型。当最终用户使用自定义字段保存记录时,会发生两件事。首先,在主数据表中创建或更新记录本身;为所有预定义字段保存值,但不保存自定义字段。相反,应用程序为记录创建唯一标识符并将其保存在“记录ID”字段中。其次,在扩展表中创建一个包含以下信息的新行:

  • 主数据表中关联记录的ID。
  • 与正确的自定义字段定义关联的扩展ID。
  • 正在保存的记录中的自定义字段的值,强制转换为字符串。

此方法允许每个租户根据需要创建尽可能多的自定义字段以满足其业务需求。当应用程序检索客户记录时,它会在扩展表中执行查找,选择与记录ID对应的所有行,并为每个使用的自定义字段返回一个值。要将这些值与正确的自定义字段相关联并将它们转换为正确的数据类型,应用程序将使用与扩展表中的每个值关联的扩展ID在元数据中查找自定义字段信息。

这种方法使数据模型可以任意扩展,同时保留使用共享数据库的成本优势。这种方法的主要缺点是它增加了数据库功能的复杂程度,例如索引,查询和更新记录。如果您希望使用共享数据库,这通常是最佳方法,但也预计您的客户需要相当大的灵活性来扩展默认数据模型。

自定义列

最简单的可扩展数据模型是可以将列直接添加到租户表中的模型。 图13.可以将自定义行添加到专用表,而无需更改其他租户的数据模型

此模式适用于单独数据库或单独模式应用程序,因为每个租户都有自己的一组表,可以独立于属于任何其他客户端的表进行修改。 从数据模型的角度来看,这是三种可扩展性模式中最简单的一种,因为它不需要您单独跟踪数据扩展。 但是,在应用程序体系结构方面,这种模式有时可能更难实现,因为它允许租户改变表中的列数。 即使您可以使用自定义列模式,也可以考虑使用预分配字段或名称 - 值对模式的变体来减少开发工作量,从而允许您编写可以在每个表中假定已知且不变的字段数的应用程序代码。

使用数据模型扩展

无论您使用何种方法创建可扩展数据模型,都必须与将其他字段集成到应用程序功能中的机制配对。 客户实现的任何自定义字段都需要对业务逻辑进行相应的修改(因此应用程序可以使用自定义数据),表示逻辑(以便用户可以输入自定义数据作为输入并将其作为输出接收) , 或两者。 因此,您提供给客户的配置界面应提供修改所有三个的方法,最好是以集成的方式。 (在本系列的后续文章中将提供客户可以修改业务逻辑和用户界面的机制。)

可伸缩性模式

大型企业软件旨在同时被成千上万的人使用。如果您具有构建此类企业应用程序的经验,那么您可以直接了解创建可扩展体系结构的挑战。对于SaaS应用程序,可伸缩性更为重要,因为您必须支持属于所有客户的数据。对于习惯于构建内部企业软件的独立软件供应商(ISV)来说,支持这种类型的用户群就像从小联盟转移到大联盟:规则可能很熟悉,但游戏的玩法完全不同。您需要积极支持可能数以百万计的用户群,而不是广泛部署的关键业务企业应用程序,而是构建一个互联网规模的系统。

可以扩展数据库(通过迁移到使用更强大的处理器,更多内存和更快的磁盘驱动器的更大的服务器)并扩展(通过将数据库分区到多个服务器上)。在扩展共享数据库与扩展专用数据库时,不同的策略是适当的。 (在开发扩展策略时,区分扩展应用程序(增加应用程序可容纳的总工作负载)和扩展数据(增加存储和处理数据的容量)非常重要。本文重点介绍具体扩展数据。)

伸缩技术

向外扩展数据库时使用的两个主要工具是复制和分区。复制涉及将全部或部分数据库复制到另一个位置,然后使一个或多个副本与原始数据保持同步。单主复制(其中只能写入原始(或复制主服务器))比多主复制更容易管理,其中可以写入部分或全部副本,并使用某种同步机制协调不同数据副本之间的更改。

分区涉及从数据库中修剪数据子集并将修剪后的数据移动到同一数据库中的其他数据库或其他表。您可以通过重定位整个表来对数据库进行分区,也可以通过将一个或多个表水平或垂直拆分为较小的表来对数据库进行分区。水平分区意味着使用相同的模式和结构将数据库划分为两个或更多个较小的数据库,但每个表中的行数较少。垂直分区意味着将一个或多个单独的表划分为具有相同行数的较小表,但每个表包含原始列的子集。在扩展数据库时,复制和分区通常彼此组合使用。

基于租户的水平分区

共享数据库在无法满足基准性能指标时应进行扩展,因为当有太多用户尝试同时访问数据库或数据库大小导致查询和更新执行时间过长或运行维护时任务开始影响数据可用性。

扩展共享数据库的最简单方法是通过基于租户ID的水平(基于行)分区。 SaaS共享数据库非常适合水平分区,因为每个租户都有自己的数据集,因此您可以轻松地定位单个租户数据并移动它。

但是,不要假设,如果您有100个租户并希望以五种方式对数据库进行分区,您可以一次只计算20个租户并移动它们。不同的租户可以对应用程序提出截然不同的要求,重要的是要仔细规划以避免简单地创建更小但仍然负担过重的分区,而其他分区未得到充分利用。

如果由于太多最终用户同时访问数据库而遇到应用程序性能问题,请考虑对数据库进行分区以均衡每台服务器上活动最终用户帐户的总数。例如,如果现有数据库为租户A和B提供每个活动用户600个,租户C,D和E各有400个活动用户,则可以通过将租户C,D和E移动到新服务器来对数据库进行分区。 ;两个数据库将分别为1200个用户提供服务。

如果您遇到与数据库大小相关的问题,例如执行查询所需的时间长度,则更有效的分区方法可能是针对数据库大小,而是以这样的方式将租户分配给数据库服务器。大致均衡每个数据的数量。

您选择的分区方法会对应用程序开发产生重大影响。无论您选择哪种方法,您都可以准确地调查和报告您打算用来制定分区决策的任何指标。建立对应用程序监控的支持将帮助您准确了解租户的使用模式和需求。此外,您可能需要定期对数据进行重新分区,因为您的租户不断发展并改变其工作方式。选择可在需要时执行的分区策略,而不会过度影响生产系统。

有时,租户可能拥有足够的用户或使用足够的数据来证明将租户移动到自己的专用数据库。请参阅下一节“单租户横向扩展”,以获取进一步扩展的帮助。

基于租户的水平分区模式适用于共享模式应用程序,这会对熟悉的数据库扩展任务施加一些不寻常的限制。它提供了一种扩展共享数据库的方法,同时避免了会破坏应用程序或损害性能的操作(例如,无意中或不必要地在两个或多个服务器之间拆分租户的数据)。

单租户横向扩展

如果部分或全部租户存储并使用大量数据,则租户数据库可能会变得足够大,足以证明将整个服务器用于为单个租户提供服务的单个数据库。这种情况下的可扩展性挑战类似于传统单租户应用程序的架构师所面临的挑战。通过专用服务器上的大型数据库,扩展是适应持续增长的最简单方法。

如果数据库继续增长,最终将其转移到功能更强大的服务器将不再具有成本效益,并且您必须通过将数据库分区到一个或多个其他服务器来扩展。扩展专用数据库与扩展共享数据库不同。使用共享数据库,最有效的扩展方法涉及将整套租户数据从一个数据库移动到另一个数据库,因此您使用的数据模型的性质并不特别相关。在扩展专用于单个租户的数据库时,有必要分析存储的数据类型以确定最佳方法。

文章Scaling Out SQL Server 2005包含有关分析数据以进行扩展的其他指导和建议。本文详细介绍了参考数据,活动数据和资源数据,提供了复制和分区数据的一些指导原则,并解释了影响横向扩展的一些其他因素。一些需要考虑的横向扩展指南:

  • 使用复制来创建不经常更改的数据的只读副本。输入数据后,某些类型的数据很少或永远不会更改,例如部件号或员工社会保险号。其他类型的数据在规定的时间段内可以进行主动更改,然后存档,例如采购订单。这些类型的数据是单向复制到可能引用它们的任何数据库的理想选择。
  • 位置,位置,位置。保持数据接近引用它的其他数据。 (在这种意义上,“关闭”通常意味着逻辑上接近而不是物理接近,尽管逻辑接近通常也意味着物理接近。)在决定是否将它们分开时考虑不同类型数据之间的关系,并使用复制来分发只读适当时,在不同数据库之间复制参考数据。 例如,如果检索客户记录的行为通常涉及从不同的表中选择客户的最近采购订单,请尝试将两个表保留在同一数据库中,或使用复制来创建适当类型数据的副本。尝试在数据中找到自然划分,以最大限度地减少需要进行的跨数据库通信的数量。例如,与特定地点相关联的数据通常可以在地理上划分。

  • 识别不应分区的数据。资源数据(例如仓库库存水平)通常不适合复制或分区。使用scaleout技术将其他数据移出服务器,使您的资源数据有更大的增长空间。如果您已经移动了所有数据但仍然遇到问题,请考虑扩展到更大的服务器以获取资源数据。

  • 尽可能使用单主复制。将更改同步到同一数据的多个副本很困难,因此如果可以,请避免使用多主复制。必须更改复制数据时,仅允许将更改写入主副本。

这种模式可以应用于所有三种方法,但只有在单个服务器无法满足单个租户的数据需求时才会发挥作用。 使用单独的数据库方法,如果租户的数据存储需求适中,每个单独的服务器可能托管数十个数据库; 在这种情况下,缩放特定服务器涉及简单地将一个或多个数据库移动到新服务器并修改应用程序的元数据以反映新数据位置。

有关常规扩展指南,请参阅Microsoft模式和实践发布的性能和可伸缩性资源。

结论

我们在本文中讨论的设计方法和模式应该可以帮助您创建对SaaS应用程序成功至关重要的信任基础层。 设计SaaS数据架构可以协调共享和隔离的竞争优势和需求并非易事,但这些方法和模式应该可以帮助您识别和解决您将面临的许多关键问题。 这里提出的想法和建议在细节上有所不同,但它们都有助于您利用可配置性,可扩展性和多租户效率原则为SaaS应用程序设计安全且可扩展的数据架构。

本文绝不是单实例,多租户数据架构中的最后一个词。 在本系列的后面部分,我们将介绍如何通过演示和工作流程自定义帮助租户充分利用其数据模型扩展。

愚蠢的白羊

继续阅读此作者的更多文章