你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
本指南介绍了为部署的数据库和数据存储技术设计数据分区策略的建议。 此策略可帮助你提高数据资产的可靠性。
在许多大规模解决方案中, 分区 用于划分数据,以便可以单独管理和访问数据。 分区数据可提高可伸缩性、减少争用并优化性能。 实现数据分区以按使用模式划分数据。 例如,可以在廉价的数据存储中存档旧数据。 请仔细选择分区策略,以最大限度地发挥优势并最大程度地减少负面影响。
注释
在本文中,术语 分区 是指将数据物理划分为单独的数据存储的过程。 它不同于 SQL Server 表分区。
可以将数据分区为:
提高缩放性。 纵向扩展单一数据库系统时,数据库最终达到物理硬件限制。 如果将数据划分为多个分区,且每个分区托管在单独的服务器上,则可以几乎无限期地横向扩展系统。
提高性能。 在每个分区中,与未分区的数据相比,数据访问作在较小的数据量上执行。 对数据进行分区,使系统更高效。 影响多个分区的作可以并行运行。
提高安全性。 在某些情况下,可以将敏感和非敏感数据分成不同的分区,并将不同的安全控制应用于敏感数据。
提供作灵活性。 可以将数据分区,以微调作、最大程度地提高管理效率并最大程度地降低成本。 例如,可以根据每个分区中数据的重要性定义管理、监视、备份和还原和其他管理任务的策略。
将数据存储与使用的模式匹配。 可以根据数据存储提供的成本和内置功能,在不同类型的数据存储上部署每个分区。 例如,可以在 Blob 存储中存储大型二进制数据,并将结构化数据存储在文档数据库中。 有关详细信息,请参阅 “了解数据存储模型”。
提高可用性。 若要避免单一故障点,可以跨多个服务器分隔数据。 如果一个实例失败,则只有该分区中的数据不可用。 作在其他分区中继续。 此注意事项与托管平台即服务(PaaS)数据存储不太相关,因为它们具有内置冗余。
选择正确的分区策略
分区数据有三种典型策略:
水平分区 (通常称为 分片)。 在此策略中,每个分区都是单独的数据存储,但所有分区具有相同的架构。 每个分区称为 分片 ,并保存一部分数据,例如一组客户订单。
垂直分区。 在此策略中,每个分区保存数据存储中项的字段子集。 这些字段根据其使用模式进行划分。 例如,经常访问的字段可能放置在一个垂直分区中,另一个分区中访问频率较低的字段。
功能分区。 在此策略中,数据根据系统中每个绑定上下文如何使用数据进行聚合。 例如,电子商务系统可以将发票数据存储在一个分区中,将产品库存数据存储在另一个分区中。
设计分区方案时,请考虑合并这些策略。 例如,可以将数据划分为分片,然后使用垂直分区进一步细分每个分片中的数据。
水平分区(分片)
下图显示了水平分区或分片的示例。 此示例将产品清单数据划分为基于产品密钥的分片。 每个分片保存连续分片键(A-G 和 H-Z)的数据(按字母顺序排列)。 执行分片时,它会将负载分散到更多计算机上,从而减少争用并提高性能。
最重要的因素是所选的分片键。 在系统运行后,很难更改密钥。 该键必须确保数据已分区,以便尽可能均匀地跨分片分散工作负荷。
分片不必大小相同。 平衡请求数更为重要。 某些分片可能很大,但分片中的每个项都有少量的访问作。 其他分片可能更小,但分片中的每个项都会更频繁地访问。 此外,请务必确保单个分片不超过数据存储的容量和处理资源的规模限制。
避免创建可能影响性能和可用性的 热 分区。 例如,如果使用客户名称的第一个字母,则它可以创建不平衡的分布,因为某些字母比其他字母更常见。 而是使用客户标识符哈希在分区之间均匀分布数据。
选择一个分片键,以最大程度地减少将来需要拆分大型分片、将小分片合并到较大的分区或更改架构。 这些作非常耗时,可能需要脱机一个或多个分片。
如果复制了分片,则可以使某些副本保持联机状态,而另一些副本则进行拆分、合并或重新配置。 但是,系统可能会限制可以在重新配置期间执行的作。 例如,副本中的数据可能标记为只读,以防止数据不一致。
有关详细信息,请参阅 分片模式。
垂直分区
垂直分区的最常见用途是降低与提取经常访问的项相关的 I/O 和性能成本。 下图显示了垂直分区的示例。 在此示例中,项的不同属性存储在不同的分区中。 一个分区保存更频繁访问的数据,包括产品名称、说明和价格。 另一个分区保存库存数据,包括库存计数和最后一个订购日期。
在此示例中,应用程序会在向客户显示产品详细信息时定期查询产品名称、说明和价格。 库存计数和最后一个排序日期位于单独的分区中,因为这两个项目通常一起使用。
请参阅垂直分区的以下优势:
可以将相对缓慢移动的数据(产品名称、说明和价格)与更动态的数据(库存水平和上次订购日期)分开。 慢移动数据是应用程序在内存中缓存的好候选项。
可以使用添加的安全控制将敏感数据存储在单独的分区中。
垂直分区可以减少所需的并发访问量。
垂直分区在数据存储中的实体级别运行,部分规范化实体以将其从 宽 项分解为一组 窄 项。 它非常适合用于面向列的数据存储,如 HBase 和 Cassandra。 如果列集合中的数据不太可能更改,请考虑在 SQL Server 中使用列存储。
功能分区
如果可以为应用程序中每个不同的业务区域标识绑定上下文,则功能分区可以提高隔离和数据访问性能。 功能分区的另一个常见用途是将读写数据与只读数据分开。 下图显示了功能分区的概述,该分区具有与客户数据分离的清单数据。
此分区策略可帮助减少系统不同部分的数据访问争用。
设计分区以实现可伸缩性
考虑每个分区的大小和工作负荷至关重要。 平衡它们,使数据分布以实现最大可伸缩性。 但是,还必须对数据进行分区,使其不超过单个分区存储的缩放限制。
在设计分区以实现可伸缩性时,请按照以下步骤作:
分析应用程序以了解数据访问模式,例如每个查询返回的结果集的大小、访问频率、固有延迟和服务器端计算处理要求。 在许多情况下,少数主要实体需要大部分处理资源。
使用此分析来确定当前和将来的可伸缩性目标,例如数据大小和工作负荷。 然后跨分区分布数据以满足可伸缩性目标。 对于水平分区,请选择正确的分片键以确保均匀分布。 有关详细信息,请参阅 分片模式。
确保每个分区有足够的资源来处理数据大小和吞吐量方面的可伸缩性要求。 根据数据存储,每个分区的存储空间量、处理能力或网络带宽可能会有限制。 如果要求可能超过这些限制,可能需要优化分区策略或进一步拆分数据。 可能需要组合两个或多个策略。
监视系统以验证数据是否按预期分布,以及分区是否可以处理负载。 实际使用情况并不总是与分析预测的内容匹配。 可能需要重新平衡分区或重新设计系统的某些部分才能产生所需的平衡。
某些云环境根据基础结构边界分配资源。 确保所选边界的限制为数据量、数据存储、处理能力和带宽的预期增长提供了足够的空间。
例如,如果使用 Azure 表存储,则单个分区在特定时间段内可以处理的请求量有限制。 有关详细信息,请参阅 标准存储帐户的可伸缩性和性能目标。 繁忙的分片可能需要比单个分区可以处理的更多资源。 可能需要重新分区分片以分散负载。 如果这些表的总大小或吞吐量超过存储帐户的容量,则可能需要创建更多存储帐户并将表分散到这些帐户中。
设计用于查询性能的分区
可以使用小型数据集和运行并行查询来提高查询性能。 每个分区应包含整个数据集的一小部分。 减少卷可以提高查询的性能。 但是,分区不是适当的数据库设计和配置的替代方法。 确保实现必要的索引。
在为查询性能设计分区时,请按照以下步骤作:
检查应用程序要求和性能。
使用业务需求来确定必须始终快速执行的关键查询。
监视系统以识别性能缓慢的查询。
确定最常执行的查询。 即使单个查询的成本最低,累积资源消耗也可能会很大。
对导致性能缓慢的数据进行分区。
限制每个分区的大小,以便查询响应时间在目标范围内。
如果使用水平分区,请设计分片键,以便应用程序可以轻松选择适当的分区。 此规范可防止查询扫描每个分区。
请考虑分区的位置。 尝试将数据保存在与访问它的应用程序和用户相近的分区中。
如果实体具有吞吐量和查询性能要求,请使用基于该实体的功能分区。 如果此分配仍不符合要求,可以添加水平分区。 单个分区策略通常足够,但在某些情况下,合并这两种策略更高效。
跨分区并行运行查询以提高性能。
设计可用性分区
对数据进行分区以提高应用程序的可用性。 分区可确保整个数据集没有单一故障点,并且可以独立管理数据集的各个子集。
请考虑以下影响可用性的因素:
确定数据的关键性。 确定关键业务数据,例如事务,以及不太关键的作数据,例如日志文件。
将关键数据存储在高可用性分区中,并创建适当的备份计划。
为不同的数据集建立单独的管理和监视过程。
在同一分区中放置具有相同严重性级别的数据,以便可以使用相同的频率进行备份。 例如,可能需要备份保存事务数据的分区,而不是保存日志记录或跟踪信息的分区。
管理单个分区。 设计分区以支持独立的管理和维护。 这种做法提供了多种优势,例如:
如果分区失败,则可以独立恢复它,而无需访问其他分区中的数据的应用程序。
按地理区域对数据进行分区允许在每个位置的非高峰时段执行计划的维护任务。 确保分区太大,防止计划内维护在此时间段内完成。
跨分区复制关键数据。 此策略可提高可用性和性能,但也可能会带来一致性问题。 需要一段时间才能将更改与每个副本同步。 在同步期间,不同的分区包含不同的数据值。
优化应用程序代码以使用分区
分区会增加系统设计和开发的复杂性。 将数据分区为系统设计的基本部分,即使系统最初仅包含单个分区也是如此。 如果以事后方式解决分区问题,则很难,因为你已经有一个要维护的实时系统。 你可能会:
必须修改数据访问逻辑。
必须迁移大量的现有数据,以便将其分布到分区中。
遇到难题,因为用户在迁移过程中希望继续使用系统。
在某些情况下,分区并不重要,因为初始数据集很小,单个服务器可以轻松处理它。 某些工作负荷可以不使用分区,但随着用户数量的增加,许多商业系统需要扩展。
一些小型数据存储也受益于分区。 例如,数百个并发客户端可能会访问小型数据存储。 如果在这种情况下对数据进行分区,则有助于减少争用并提高吞吐量。
设计数据分区方案时,请考虑以下几点:
最大程度地减少跨分区数据访问作。 尝试将数据保存在分区中最常见的数据库作中,以最大程度地减少跨分区数据访问作。 跨分区查询而不是在单个分区中进行查询可能更耗时。 但是,为一组查询优化分区可能会对其他查询集产生不利影响。 如果必须跨分区查询,请通过运行并行查询并聚合应用程序中的结果来最大程度地减少查询时间。 在某些情况下,不能使用此方法,例如,如果下一个查询中使用了一个查询的结果。
复制静态引用数据。 如果查询使用相对静态的引用数据(如邮政编码表或产品列表),请考虑在所有分区中复制此数据,以减少不同分区中的单独查找作。 此方法还可以减少引用数据成为来自整个系统的大量流量 的热 数据集的可能性。 与同步对引用数据的更改相关的额外成本。
最小化跨分区联接。 在可能的情况下,最大程度地减少跨垂直分区和功能分区的引用完整性要求。 在这些方案中,应用程序负责跨分区维护引用完整性。 跨多个分区联接数据的查询效率低下,因为应用程序通常执行基于键和外键的连续查询。 相反,请考虑复制或取消规范化相关数据。 如果需要跨分区联接,请对分区运行并行查询,并联接应用程序中的数据。
实现最终一致性。 评估强一致性是否是必需的。 分布式系统中的一种常见方法是实现最终一致性。 每个分区中的数据单独更新,应用程序逻辑可确保更新成功完成。 应用程序逻辑还处理在最终一致的作运行时查询数据产生的不一致。
请考虑查询如何查找正确的分区。 如果查询必须扫描所有分区才能找到所需的数据,即使运行多个并行查询,它也会显著影响性能。 使用垂直分区和功能分区,查询可以指定分区。 另一方面,水平分区可能会使定位项变得困难,因为每个分片具有相同的架构。 典型的解决方案是维护用于查找项分片位置的映射。 在应用程序的分片逻辑中实现此映射。 如果数据存储支持透明分片,则数据存储还可以维护它。
定期重新平衡分片。 使用水平分区,重新均衡分片有助于按大小和工作负荷均匀分配数据。 重新平衡分片,以最大程度地减少热点、最大化查询性能,以及解决物理存储限制。 此任务很复杂,通常需要自定义工具或流程。
复制分区。 复制每个分区以提供针对故障的附加保护。 如果单个副本失败,则查询将定向到工作副本。
将可伸缩性扩展到不同的级别。 如果达到分区策略的物理限制,可能需要将可伸缩性扩展到不同的级别。 例如,如果分区位于数据库级别,则可能需要在多个数据库中查找或复制分区。 如果分区已在数据库级别,并且存在物理限制,则可能需要在多个托管帐户中找到或复制分区。
避免访问多个分区中的数据的事务。 某些数据存储对修改数据的作实现事务一致性和完整性,但前提是数据位于单个分区中。 如果需要跨多个分区的事务支持,请将其作为应用程序逻辑的一部分实现,因为大多数分区系统不提供本机支持。
所有数据存储都需要一些作管理和监视活动。 这些任务包括加载数据、备份和还原数据、重新组织数据以及确保系统能够正确高效地执行。
请考虑以下影响运营管理的因素:
对数据进行分区时,实现适当的管理和作任务。 这些任务可能包括备份和还原、存档数据、监视系统和其他管理任务。 例如,在备份和还原作期间保持逻辑一致性可能很困难。
将数据加载到多个分区中,并添加来自其他源的新数据。 某些工具和实用工具可能不支持分片数据作,例如将数据加载到正确的分区。
定期存档和删除数据。 为了防止分区的过度增长,每月存档和删除数据。 可能需要转换数据以匹配不同的存档架构。
查找数据完整性问题。 请考虑运行定期进程来查找数据完整性问题,例如一个分区中的数据引用另一个分区中缺少的信息。 该过程可以自动尝试修复这些问题,也可以生成报告进行手动评审。
重新平衡分区
随着系统成熟,可能需要调整分区方案。 例如,单个分区可能会开始接收不成比例的流量并变得热,从而导致争用过多。 或者,你可能低估了某些分区中的数据量,这会导致分区接近容量限制。
某些数据存储(例如 Azure Cosmos DB)可以自动重新平衡分区。 在其他情况下,可以在两个阶段重新平衡分区:
确定新的分区策略。
需要拆分或组合哪些分区?
新分区键是什么?
将数据从旧分区方案迁移到新分区集。
重新定位数据(称为 脱机迁移)时,可能需要使分区不可用。 根据数据存储,可以在分区之间迁移数据,而分区正在使用这些数据。 此方法称为 联机迁移。
脱机迁移
脱机迁移可减少争用的可能性。 若要执行脱机迁移,请执行以下作:
将分区标记为脱机。 可以将分区标记为只读,以便应用程序在移动分区时仍可读取数据。
拆分合并并将数据移动到新分区。
验证数据。
使新分区联机。
删除旧分区。
联机迁移
与脱机迁移相比,联机迁移更为复杂,但中断性更低。 此过程类似于脱机迁移,但不会将原始分区标记为脱机。 根据迁移过程的粒度,例如逐项排序,而不是分片分片,客户端应用程序中的数据访问代码可能需要读取和写入位于两个位置的数据,即原始分区和新分区。
Azure 便利化
以下部分介绍有关对 Azure 服务中存储的数据进行分区的建议。
Azure SQL 数据库中的分区
单个 SQL 数据库对可以包含的数据量有限制。 吞吐量受体系结构因素及其支持的并发连接数的约束。
弹性池 支持 SQL 数据库的水平缩放。 使用弹性池将数据分区为分布在多个 SQL 数据库的分片中。 还可以在数据量增长和收缩时添加或删除分片。 弹性池还可以通过跨数据库分配负载来帮助减少争用。
每个分片都作为 SQL 数据库实现。 分片可以保存多个数据集。 每个数据集称为 shardlet。 每个数据库都有描述其包含的 shardlet 的元数据。 shardlet 可以是单个数据项,也可以是共享同一 shardlet 键的一组项。 例如,在多租户应用程序中,shardlet 密钥可以是租户 ID,租户的所有数据都可以位于同一 shardlet 中。
应用程序负责将数据集与 shardlet 密钥相关联。 单独的 SQL 数据库充当全局分片映射管理器。 此数据库包含系统中所有分片和 shardlet 的列表。 应用程序连接到分片映射管理器数据库以获取分片映射的副本。 它会在本地缓存分片映射,并使用映射将数据请求路由到相应的分片。 此功能隐藏在 SQL 数据库的弹性数据库功能的客户端库中(适用于 Java 和 .NET)的一系列 API 后面。
有关弹性池的详细信息,请参阅 使用 SQL 数据库横向扩展。
若要降低延迟并提高可用性,可以复制全局分片映射管理器数据库。 使用高级定价层,可以配置活动异地复制,以持续将数据复制到不同区域中的数据库。
或者,使用 SQL 数据库或 Azure 数据工厂的 SQL 数据同步跨区域复制分片映射管理器数据库。 这种形式的复制会定期运行,如果分片映射不常更改且不需要高级层,则更合适。
弹性数据库提供了两种方案,用于将数据映射到 shardlet 并将其存储在分片中:
列表分片映射将单个键与 shardlet 相关联。 例如,在多租户系统中,每个租户的数据可以与唯一密钥相关联,并存储在其自己的 shardlet 中。 为了保证隔离,每个 shardlet 可以保存在其自己的分片中。
下载此图的 Visio 文件。
范围分片映射将一组连续键值与 shardlet 相关联。 例如,可以在同一 shardlet 中对一组租户(每个租户都有自己的密钥)进行分组。 此方案的成本低于列表分片映射,因为租户共享数据存储,但它提供较少的隔离。
下载此关系图的 Visio 文件
单个分片可以包含多个 shardlet 的数据。 例如,可以使用列表 shardlet 在同一分片中存储不同非连续租户的数据。 还可以在同一分片中混合范围 shardlet 和列出 shardlet,但随后会通过不同的映射对它们进行寻址。 下图显示了此方法:
下载此图的 Visio 文件。
使用弹性池,可以在数据量增长和收缩时添加和删除分片。 客户端应用程序可以动态和透明地创建和删除分片映射管理器。 但是,删除分片是一项破坏性作,还需要删除该分片中的所有数据。
如果应用程序需要将分片拆分为两个单独的分片或合并分片,请使用 拆分/合并工具。 此工具作为 Azure Web 服务运行,并在分片之间安全地迁移数据。
分区方案可能会显著影响系统的性能。 它还会影响必须添加或删除分片的速率,或者必须跨分片重新分区数据。 请考虑以下几点:
将同一分片中一起使用的数据分组,并避免访问多个分片中的数据的作。 分片是自己的 SQL 数据库,当作访问多个分片时,必须在客户端上执行跨数据库联接。
尽管 SQL 数据库不支持跨数据库联接,但可以使用弹性数据库工具来执行 多分片查询。 多分片查询将单个查询发送到每个数据库并合并结果。
设计一个在分片之间没有依赖关系的系统。 引用完整性约束、触发器和一个数据库中的存储过程不能引用另一个数据库中的对象。
如果你有查询经常使用的引用数据,请考虑跨分片复制数据。 这种方法可以消除跨数据库联接数据的需求。 理想情况下,此类数据应该是静态的或缓慢移动的,以尽量减少复制工作,并降低它变得过时的可能性。
对属于同一分片映射的 shardlet 使用相同的架构。 SQL 数据库不会强制执行本指南,但如果每个 shardlet 具有不同的架构,数据管理和查询就很复杂。 而是为每个架构创建单独的分片映射。 可以将属于不同 shardlet 的数据存储在同一分片中。
如果业务逻辑需要执行事务,请将数据存储在同一分片中或实现最终一致性。 事务作仅支持分片中的数据,而不支持跨分片。 如果事务属于同一分片,则事务可以跨越 shardlet。
将分片靠近访问这些分片中的数据的用户。 此策略有助于降低延迟。
避免将高度活动和非活动分片组合在一起。 尝试在分片之间均匀分布负载。 可能需要对分片键进行哈希处理。 如果要定位分片,请确保哈希键映射到存储在靠近访问该数据的用户的分片中保存的 shardlet。
Azure Blob 存储中的分区
使用 Blob 存储,可以存储大型二进制对象。 在需要快速上传或下载大量数据的方案中使用块 Blob。 对需要随机(而不是串行)访问部分数据的应用程序使用页 Blob。
每个块 Blob 或页 Blob 保存在 Azure 存储帐户中的容器中。 使用容器对具有相同安全要求的相关 Blob 进行分组。 此分组是逻辑的,而不是物理的。 在容器中,每个 Blob 都有唯一的名称。
Blob 的分区键是帐户名称、容器名称和 Blob 名称。 分区键用于将数据分区为范围。 这些范围在整个系统中进行负载均衡。 Blob 可以分布在多个服务器上,以横向扩展对这些服务器的访问。 单个 Blob 只能由单个服务器提供。
如果命名方案使用时间戳或数字标识符,则可能会导致流量过多到一个分区。 它可防止系统有效地进行负载均衡。 例如,如果有使用时间戳的 blob 对象的每日作(例如 yyyy-mm-dd),则该作的所有流量将转到单个分区服务器。 而是使用三位数哈希作为名称前缀。 有关详细信息,请参阅 分区命名约定。
写入单个块或页面的作是原子作,但跨块、页或 Blob 的作不是。 如果需要确保在跨块、页面和 Blob 执行写入作时保持一致性,请使用 Blob 租约获取写入锁。
注意事项
数据分区引入了一些需要考虑的挑战和复杂性。
分区之间的数据同步可能会成为挑战。 确保以及时且一致的方式将一个分区的更新或更改传播到其他分区。
需要协调多个分区的备份和还原时,故障转移和灾难恢复过程会变得复杂。 如果某些分区或其备份损坏或不可用,则可能会出现数据完整性问题。
如果需要跨分区进行查询,并且重新平衡分区(如果数据增长不均匀),则数据分区可能会影响性能和可靠性。