Web 应用程序的数据库横向扩展策略






4.20/5 (4投票s)
根据需求不同,扩展 Web 应用和数据库的规模可能会非常复杂,但好消息是,对于大多数 Web 应用来说,只要在设计周期开始时就考虑到这一点,就可以在对项目的时间表或预算影响很小的情况下实现。
引言
令人惊讶的是,Web 应用的使用量可以如此迅速地超出最初的预期。增长对业务有利,但在保持一切正常运行并快速响应方面会带来一些真正的挑战。在设计应用程序时,会根据预期的最大 Web 流量负载和数据库需要处理的并发请求数量进行估算。通常,这些估算会过于保守(有时甚至完全错误),因此软件架构师需要为更大的应用程序负载做好计划,以避免未来的大规模重新设计。这些计划通常需要包括数据库横向扩展策略。根据需求不同,扩展 Web 应用和数据库的规模可能会非常复杂,但好消息是,对于大多数 Web 应用来说,只要在设计周期开始时就考虑到这一点,而不是事后诸葛,就可以在对项目的时间表或预算影响很小的情况下实现。
纵向扩展与横向扩展
扩展应用程序最常见的方法是纵向扩展。本质上,纵向扩展就是不断增加服务器上的资源(硬件),使其能够处理更多的负载和用户请求。这种方法之所以如此普遍,是因为它不需要修改实际的应用程序,而且所有数据都集中在一个地方,这无疑有助于降低复杂性和维护成本。
第二种,也是更复杂的方法是横向扩展。基本思想是将数据分区到多个数据库服务器中,从而将应用程序的负载分散到多个服务器上。
虽然横向扩展 Web 服务器相对容易,但正确地横向扩展数据库服务器则更具挑战性,而这正是本文的重点。
横向扩展数据库服务器
SQL Server 2005 和 2008 都原生提供了一些横向扩展数据库的选项。这些选项包括共享数据库、复制、链接服务器、分布式分区视图以及面向服务的 डेटा 体系结构。这些技术各有优缺点,在微软的网站和网络上的许多其他资源中都有详细介绍,因此我在这里不赘述。相反,我将重点介绍一种被认为是横向扩展数据库最有效的方式,而且这种方式与任何特定的数据库供应商都没有直接关联。这种策略称为数据相关路由 (DDR)。
在上图的示意图中,您可以看到应用程序服务器如何接收到搜索新泽西州客户的请求,并将其路由到新泽西州客户数据库进行处理。
数据相关路由 (DDR)
数据相关路由,在其最基本的形式下,允许软件架构师以一种底层应用程序已知的方式,将应用程序的数据分区到多个数据库中。因此,应用程序接收数据库请求,并将其适当地路由到正确的数据库进行处理。尽管这种方法比其他横向扩展选项更复杂,但它提供了前所未有的灵活性和无与伦比的性能提升。
数据分区
实施 DDR 应用程序时,软件架构师面临的挑战之一是如何确切地分区数据,以平衡性能与维护成本。理想情况下,您希望获得最佳性能和非常低的维护成本。不幸的是,并非所有情况都有一种答案,因此了解各种选项并决定最适合每个应用程序的方案非常重要。
通常,有两种数据分区选项
水平数据分区
在水平数据分区中,数据库结构在多个数据库实例之间是相同的。它们之间的唯一区别在于它们包含的数据。例如,我们可以按客户所在地区分离数据,一个数据库用于新泽西州客户,另一个数据库用于纽约州客户。
垂直数据分区
在垂直数据分区中,实际的表被分割到多个数据库实例中。每个数据库实例通常处理不同的数据集。例如,我们可能希望将与销售相关的数据配置在一个数据库中,将与营销相关的数据配置在另一个数据库中。
尽管这两种选择都可行,但本文将重点介绍水平数据分区,因为它在许多场景下更容易理解和实现。因此,让我们深入到一个用例。
水平数据分区的用例
应用程序概述
让我们假设我们正在设计一个 Web 应用程序,该应用程序将服务于许多中大型公司。我们还假设每家公司都有自己的特定数据和用户,并且公司之间的数据从不共享。应用程序的确切性质对我们的用例来说并不重要,但就我们的目的而言,它可以维护用户的联系数据以及与业务运营相关的其他数据。
应用程序架构
根据上述描述,并假设在最极端的情况下,我们将为每家公司分配一个数据库服务器,我们可以轻松地按以下方式构建应用程序:
每家公司将被分配一个“主数据库”来存储其所有用户和数据。我们将维护一个中央数据库(“邮件中心”数据库)来存储系统中的所有用户以及它们的相应主数据库列表,以便在运行时确定哪个数据库应该处理每个请求。
整体应用程序架构可能如下所示:
上图包括一个用于处理应用程序界面的 Web 场、几个用于处理业务逻辑和数据库路由的应用程序服务器、一个用于存储用户到主数据库映射的中央数据库,以及几个分别存储特定公司数据的home databases。
中央数据库设计
在我们的例子中,中央数据库相当简单,包含以下三个表:
- home_databases – 存储用于构建连接到每个主数据库的连接字符串的必要信息。
- clients – 存储我们的客户(公司)信息,并将每个客户与一个主数据库关联起来。
- users – 存储系统中的所有用户、他们的内部 ID、电子邮件以及客户关联,以便我们在运行时确定他们相应的主数据库。
主数据库设计
每个主数据库将包含以下表(除了其正常的业务数据):
- users – 存储用户身份验证信息(电子邮件、密码等)。
- tokens – 存储用户令牌。令牌在用户登录时创建,并包含应用程序用于标识用户主数据库以供将来调用和授权的信息。
应用程序操作示例
一旦我们配置了数据库基础结构,让我们在两种常见场景下检查我们的应用程序是如何操作的:登录和查询数据。
登录操作
输入:用户的电子邮件和密码。
输出:用户的授权令牌。
进程
- 用户提供他们的电子邮件地址和密码。
- 应用程序将联系中央数据库,并根据提供的电子邮件确定用户的home database。
- 应用程序将联系用户的home database,并验证提供的凭据。
- 成功验证后,应用程序将创建一个包含用户 home database 标识符和可能其他信息的唯一令牌。这种方法将有助于我们避免在用户每次调用时都联系中央数据库来查找正确的 home database。
- 应用程序将令牌返回到客户端代码,以便令牌可以用于将来的调用。
查询数据
输入:用户的令牌和任何用于查询的附加数据。
输出:用户请求的数据。
进程
- 应用程序提取令牌的信息并确定用户的 home database。
- 令牌会在相应的 home database 上进行验证。
- 将在用户的 home database 上调用相应的查询(可能需要在实际数据库查询调用之前进行授权)。
- 应用程序将适当的数据返回到客户端代码进行处理(例如,在浏览器上显示)。
其他横向扩展主题
配置数据
通常,您的应用程序可能需要一些配置数据在所有 home databases 上可用。配置数据通常是相当静态的。一种可能的解决方案是将此信息保留在中央数据库中,并使用内置的复制体系结构将其复制到所有其他 home databases。
共享数据
有时应用程序数据需要在多个 home databases 之间共享。例如,如果多个 home databases 中的用户可以相互联系,并且我们希望显示某个特定用户发送和接收的所有请求。您可以考虑将所需的所有数据保留在某个特定的 home database 中,并将其一部分数据复制到可能需要的其他 home databases。
有几种方法可以做到这一点,其中两种方法对 Scopings 非常有效。当您需要将信息记录到两个或三个数据库中时,我们使用分布式事务;当您需要与更多 home databases 共享信息时,我们使用 Service Broker。
跨数据库查询
您可能会发现需要通过查询多个数据库中的数据来处理某些请求。微软为此目的引入的选项之一是链接服务器。这允许开发人员针对多个数据库和服务器运行查询和连接,这可能非常适合这种情况。不幸的是,除非应用程序基础结构非常简单且可以轻松分配链接服务器,否则维护起来可能会变得相当复杂。
我们发现一种非常有效的方法是实现一个存储过程,该存储过程仅从其特定数据库检索数据,并以 XML 格式返回数据。这样,应用程序可以查询任意数量的数据库,然后轻松地将从所有数据库检索到的 XML 合并到一个 XML 文档中。然后,客户端可以使用 XSLT 像从一个普通查询中检索数据一样处理合并后的 XML。
分布式数据库存储
在服务于许多小型实体(这些实体可能相互交互,也可能不交互)的应用程序中,通常需要控制实体在所有可用 home databases 之间的分布。这可以通过在中央数据库中管理可用 home databases 及其数据属性的列表来实现,这样应用程序代码就可以在运行时确定最适合创建下一个新实体的数据库。
如果您发现某些 home databases 因事务过多而负担过重,而其他 home databases 则大部分时间处于空闲状态,您还可能希望开发一个应用程序管理过程,以便在 home databases 之间移动实体。
排队处理
有时您可能会处理比最初设想的更多的并发请求,或者在某些时候(例如,在纳税截止日期之前)可能会出现激增的请求。SQL Server 2005,现在还有 SQL Server 2008 的一个非常有用的特性是 Service Broker。Service Broker 可用于处理异步事务处理、复制等。在适当的情况下,您绝对应该考虑使用它,因为您的应用程序的硬件需求可能会大大降低。
结论
设计一个可横向扩展的基础结构绝非易事,但它有时可以成就或毁掉您的应用程序。请记住,在开发开始时就为扩展进行设计,比在应用程序上线后才考虑要容易得多。