你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
适用于:Azure SQL 数据库
要轻松横向扩展 Azure SQL 数据库上的数据库,请使用分片映射管理器。 分片映射管理器是一个特殊的数据库,它维护一个分片集中有关所有分片(数据库)的全局映射信息。 元数据允许应用程序基于 分片键值连接到正确的数据库。 此外,在集中的每个分片都包含跟踪本地分片数据的映射(称为 shardlet)。
了解如何构建这些映射对于分片映射管理至关重要。 这是通过在 构建可扩展的云数据库 中找到的 ShardMapManager 类 (Java, .NET)来管理分片映射。
分片映射
对于每个分片,必须选择要创建的分片映射类型。 选择取决于数据库架构:
- 每个数据库一个租户
- 每个数据库多个租户(两种类型):
- 列表映射
- 范围映射
对于单租户模型,创建列表映射分片映射。 单租户模型将每个租户分配给一个数据库。 这是适用于 SaaS 开发人员的有效模型,因为它可以简化分片映射管理。
多租户模型将数个租户分配给单个数据库(可跨多个数据库分布租户组)。 如果希望每个租户具有较小的数据需求,请使用此模型。 在此模型中,使用范围映射将一系列用户分配到数据库。
或可以使用列表映射来实现多租户数据库模型,以将多个租户分配给单个数据库。 例如,DB1 用于存储租户 ID 1 和 5 的相关信息,而 DB2 用于存储租户 7 和租户 10 的数据。
支持的分片键的类型
灵活扩展支持将以下类型用作分片键:
。网 | 爪哇岛 |
---|---|
整数 | 整数 |
长整型 | 长整型 |
GUID | UUID(通用唯一识别码) |
byte[] | byte[] |
datetime | 时间戳 |
时间跨度 | 持续时间 |
日期时间偏移量 | offsetdatetime |
列表和范围分片映射
使用各个分片键值的列表或分片键值的范围可构造分片映射 。
列表分片映射
分片包含 shardlet,shardlet 到分片的映射由分片映射维护 。 列表分片映射 是可标识 shardlet 的单独键值和可用作分片的数据库之间的关联项。 是可以映射到同一个数据库的显式且不同的键值。 例如,键值 1 映射到数据库 A,键值 3 和 6 都映射到数据库 B。
键 | 分片位置 |
---|---|
1 | Database_A |
3 | Database_B |
4 | Database_C |
6 | Database_B |
... | ... |
范围分片映射
在范围分片映射中,键范围由 [Low Value, High Value) 对描述,其中 Low Value 是范围中的最小键,而 High Value 是第一个大于范围的值 。
例如,[0, 100) 包括所有大于或等于 0 且小于 100 的整数。 多个范围可以指向同一数据库,并且支持不连续的范围(例如 [100,200) 和 [400,600) 都指向以下示例中的数据库 C。
键 | 分片位置 |
---|---|
[1至50) | Database_A |
[50,100) | Database_B |
[100,200) | Database_C |
[400,600) | Database_C |
... | ... |
上面所示的每个表都是对象 ShardMap
的概念示例。 每行都是单个 PointMapping
(列表分片映射)或 RangeMapping
(对于范围分片映射)对象的简化示例。
分片映射管理器
在客户端库中,分片映射管理器是分片映射的集合。 实例管理的数据保存在三个 ShardMapManager
位置:
-
全局分片映射 (GSM) :指定一个数据库以用作它的所有分片映射和映射的存储库。 自动创建特殊的表和存储过程以管理信息。 这通常是小型数据库且可轻松进行访问,但不应用于满足应用程序的其他需求。 这些表位于名为
__ShardManagement
的特殊架构中。 -
局部分片映射 (LSM) :修改指定为分片的每个数据库,以包含多个小表和特殊存储过程,其中包括特定于该分片的分片映射信息并对其进行管理。 对于 GSM 中的信息而言,该信息是冗余的,但应用程序通过该信息可验证缓存的分片映射信息,而无需将所有负载置于 GSM 上;应用程序可使用 LSM 确定缓存的映射是否仍然有效。 与每个分片上的 LSM 对应的表也位于架构
__ShardManagement
中。 -
应用程序缓存:访问
ShardMapManager
对象的每个应用程序实例都维护其映射的本地内存中缓存。 它存储最近检索到的路由信息。
构造一个 ShardMapManager
对象 ShardMapManager
是使用工厂 (Java, .NET) 模式构造的。 通过 ShardMapManagerFactory.GetSqlShardMapManager
(Java、.NET)方法可获取具有 ConnectionString
形式的凭据(包括用于保存 GSM 的服务器名称和数据库名称),并返回 ShardMapManager
的实例。
注释
ShardMapManager
在应用程序的初始化代码中,每个应用域只能实例化一次。 在同一应用域中创建其他实例 ShardMapManager
会导致应用程序的内存和 CPU 使用率增加。 A ShardMapManager
可以包含任意数量的分片映射。 虽然单个分片映射可能足以用于许多应用程序,但有时不同的数据库集用于不同的架构或用于唯一目的:在这些情况下,多个分片映射是可取的。
在此代码中,应用程序尝试使用 ShardMapManager
(TryGetSqlShardMapManager
, .NET 方法)打开现有代码。 如果表示 Global ShardMapManager
(GSM) 的对象尚不存在于数据库中,则客户端库使用 CreateSqlShardMapManager
(Java, .NET) 方法创建它们。
// Try to get a reference to the Shard Map Manager in the shardMapManager database.
// If it doesn't already exist, then create it.
ShardMapManager shardMapManager = null;
boolean shardMapManagerExists = ShardMapManagerFactory.tryGetSqlShardMapManager(shardMapManagerConnectionString,ShardMapManagerLoadPolicy.Lazy, refShardMapManager);
shardMapManager = refShardMapManager.argValue;
if (shardMapManagerExists) {
ConsoleUtils.writeInfo("Shard Map %s already exists", shardMapManager);
}
else {
// The Shard Map Manager does not exist, so create it
shardMapManager = ShardMapManagerFactory.createSqlShardMapManager(shardMapManagerConnectionString);
ConsoleUtils.writeInfo("Created Shard Map %s", shardMapManager);
}
// Try to get a reference to the Shard Map Manager via the Shard Map Manager database.
// If it doesn't already exist, then create it.
ShardMapManager shardMapManager;
bool shardMapManagerExists = ShardMapManagerFactory.TryGetSqlShardMapManager(
connectionString,
ShardMapManagerLoadPolicy.Lazy,
out shardMapManager);
if (shardMapManagerExists)
{
Console.WriteLine("Shard Map Manager already exists");
}
else
{
// Create the Shard Map Manager.
ShardMapManagerFactory.CreateSqlShardMapManager(connectionString);
Console.WriteLine("Created SqlShardMapManager");
shardMapManager = ShardMapManagerFactory.GetSqlShardMapManager(
connectionString,
ShardMapManagerLoadPolicy.Lazy);
// The connectionString contains server name, database name, and admin credentials for privileges on both the GSM and the shards themselves.
}
对于 .NET 版本,可以使用 PowerShell 来创建新的分片映射管理器。
获取 RangeShardMap 或 ListShardMap
创建分片映射管理器以后,可以使用 TryGetRangeShardMap(Java、.NET)、TryGetListShardMap(Java、.NET)或 GetShardMap(Java、.NET)方法获取 RangeShardMap(Java、.NET)或 ListShardMap(Java、.NET)。
// Creates a new Range Shard Map with the specified name, or gets the Range Shard Map if it already exists.
static <T> RangeShardMap<T> createOrGetRangeShardMap(ShardMapManager shardMapManager,
String shardMapName,
ShardKeyType keyType) {
// Try to get a reference to the Shard Map.
ReferenceObjectHelper<RangeShardMap<T>> refRangeShardMap = new ReferenceObjectHelper<>(null);
boolean isGetSuccess = shardMapManager.tryGetRangeShardMap(shardMapName, keyType, refRangeShardMap);
RangeShardMap<T> shardMap = refRangeShardMap.argValue;
if (isGetSuccess && shardMap != null) {
ConsoleUtils.writeInfo("Shard Map %1$s already exists", shardMap.getName());
}
else {
// The Shard Map does not exist, so create it
try {
shardMap = shardMapManager.createRangeShardMap(shardMapName, keyType);
}
catch (Exception e) {
e.printStackTrace();
}
ConsoleUtils.writeInfo("Created Shard Map %1$s", shardMap.getName());
}
return shardMap;
}
// Creates a new Range Shard Map with the specified name, or gets the Range Shard Map if it already exists.
public static RangeShardMap<T> CreateOrGetRangeShardMap<T>(ShardMapManager shardMapManager, string shardMapName)
{
// Try to get a reference to the Shard Map.
RangeShardMap<T> shardMap;
bool shardMapExists = shardMapManager.TryGetRangeShardMap(shardMapName, out shardMap);
if (shardMapExists)
{
ConsoleUtils.WriteInfo("Shard Map {0} already exists", shardMap.Name);
}
else
{
// The Shard Map does not exist, so create it
shardMap = shardMapManager.CreateRangeShardMap<T>(shardMapName);
ConsoleUtils.WriteInfo("Created Shard Map {0}", shardMap.Name);
}
return shardMap;
}
分片映射管理凭据
用于管理和操作分片映射的应用程序不同于那些使用分片映射路由连接的应用程序。
若要管理分片映射(添加或更改分片、分片映射等),必须使用ShardMapManager
实例化 。 在输入或更改分片映射信息时,这些凭据必须允许编写 GSM 和 LSM 中的表,以及在新分片上创建 LSM 表。
请参阅用于访问弹性数据库客户端库的凭据。
仅元数据受影响
用于填充或更改 ShardMapManager
数据的方法不会更改存储在分片本身中的用户数据。 例如,方法如 CreateShard
, DeleteShard
, UpdateMapping
等仅影响分片映射元数据。 不会删除、添加或更改分片中所包含的用户数据。 但是,这些方法旨在与你执行的单独操作结合使用,以创建或删除实际数据库,或者将行从一个分片移动到另一个分片,以使分片环境恢复均衡。 弹性数据库工具中的拆分-合并工具利用这些 API,并协调分片之间的实际数据移动。请参阅在横向扩展的云数据库之间移动数据。
依赖于数据的路由
分片映射管理器主要由需要数据库连接的应用程序用来执行特定于应用的数据操作。 这些连接必须与正确的数据库关联。 这称为 依赖于数据的路由。 对于这些应用程序,通过使用在 GSM 数据库上具有只读访问权限的凭据,实例化来自工厂的分片映射管理器对象。 以后,单独的连接请求将提供连接相应分片数据库时所需的凭据。
这些应用程序(使用 ShardMapManager
只读凭据打开)无法更改地图或映射。 为了满足这些需求,请创建特定于管理的应用程序或 PowerShell 脚本,以提供如前所述的更高级别权限的凭据。 请参阅用于访问弹性数据库客户端库的凭据。
有关详细信息,请参阅 使用依赖于数据的路由将查询路由到适当的数据库。
修改分片映射
可采用不同方式更改分片映射。 以下所有方法都可修改用于描述分片及其映射的元数据,但这些方法不以物理方式修改分片内的数据,也不创建或删除实际数据库。 在分片映射上执行以下某些操作时,可能需要配合管理行动,这些行动涉及物理移动数据或添加和删除作为分片的数据库。
这些方法作为构建基块一同工作,以便在分片的数据库环境中修改数据的总体分发情况。
若要添加或删除分片:使用
CreateShard
分片映射类(Java,.NET)和DeleteShard
(Java,.NET)。- 若要执行这些操作,表示目标分片的服务器和数据库必须已经存在。 这些方法不会对数据库本身产生任何影响,仅对分片映射上的元数据产生影响。
要创建或删除映射到分片的点或范围,请使用 RangeShardMapping 类中的
CreateRangeMapping
方法(Java, .NET),DeleteMapping
方法(Java, .NET)以及 ListShardMap 类中的 方法(Java,CreatePointMapping
),来管理这些点或范围。许多不同的点或范围可映射到相同的分片。 这些方法仅影响元数据 - 它们不会影响任何可能已存在于分片中的数据。 如果需要从数据库中删除数据以便与
DeleteMapping
操作保持一致,请单独执行这些操作,同时结合使用这些方法。若要将现有范围拆分为两个区域,或将相邻范围合并为一个范围:使用
SplitMapping
(Java、 .NET) 和MergeMappings
(Java, .NET)。拆分和合并操作 不会更改键值映射到的分片。 拆分操作可将现有范围拆分为两个部分,但在映射到相同分片时同时保留这两个部分。 对在已映射到相同分片的两个相邻范围进行合并操作,从而可将其合并到单个范围中。 要在分片之间移动点或范围本身,需要将
UpdateMapping
与实际数据移动结合使用,才能进行协调。 当需要移动数据时,可以使用弹性数据库工具中随附的拆分/合并服务,以将分片映射更改与数据移动相协调。若要将各个点或范围重新映射到不同的分片:使用
UpdateMapping
(Java、 .NET)。由于数据可能需要从一个分片移动到另一个分片,以保持与
UpdateMapping
操作的一致性,因此需要单独执行移动操作,但要与这些方法结合进行。若要使映射联机和脱机:使用
MarkMappingOffline
(Java、 .NET) 和MarkMappingOnline
(Java, .NET) 控制映射的联机状态。只有当映射处于脱机状态时,才允许对分片映射执行某些操作,包括
UpdateMapping
和DeleteMapping
。 当映射处于脱机状态时,基于该映射中所包含的键的数据依赖请求将返回一个错误。 此外,当范围首次处于脱机状态时,所有到受影响分片的连接都会自动终止,以防止因范围的更改而导致查询出现不一致或不完整的结果。
映射是 .NET 中的不可变对象。 以上会更改映射的所有方法也会使代码中任何对映射的引用失效。 为了更轻松地执行操作序列来更改映射的状态,所有会更改映射的方法都将返回新的映射引用,以便能够链接操作。 例如,若要在 shardmap sm 中删除包含键 25 的现有映射,可以执行以下命令:
sm.DeleteMapping(sm.MarkMappingOffline(sm.GetMappingForKey(25)));
添加分片
对于已经存在的分片映射,应用程序通常仅需要添加新分片,以处理预期的新键或键范围数据。 例如,按租户 ID 分片的应用程序可能需要为新租户预配新分片,或者每月分片的数据可能需要在每个新月开始之前预配的新分片。
如果新的键值范围还不是现有映射的组成部分且无需移动数据,则添加新分片以及将新的键或范围关联到该分片非常简单。 有关添加新分片的详细信息,请参阅 使用弹性数据库工具添加分片。
但是,在需要移动数据的情况下,需要拆分/合并工具并结合使用必要的分片映射更新,才能安排在分片之间移动数据。 有关使用拆分-合并工具的详细信息,请参阅在横向扩展云数据库之间移动数据
相关内容
尚未使用弹性数据库工具? 请查看入门指南。 如有问题,请在有关 SQL 数据库的 Microsoft Q&A 问题页面上联系我们;如有功能请求,请在 SQL 数据库反馈论坛添加新意见或为现有意见投票。