3

在 Azure 中,我们有四个 Shard,我想删除其中两个,因为我们不再需要它们。数据应合并到其他两个分片中。

我使用带有 GUID 的 Listmap 作为 Key 来识别 Shard(在我们的应用程序中,这是 UserId)。在教程中,我只找到了将 Shards 与 Range 类型合并的示例。有没有办法以更快的方式合并这些类型的分片,还是我必须为此编写自己的工具?

如果自动执行合并,例如在以下情况下会发生什么情况:标识分片的 GUID 是 UserId,现在此数据从分片 A 移动到分片 B。还有另一个名为 Comments 的表,其 UserId 为 ForeignKey . 此表中的 PrimaryKey 是一个经典的数字自增值。如果这些值从分片 A 移动到分片 B,它们会发生什么?是否会插入它们并为它们分配一个新 ID,或者这根本不起作用?

还有一些本地 FileStorage invloved 在路径中使用 ID,所以无论如何我都必须编写自己的工具。

为此,我查看了 ShardMapManager,但并没有完全理解它是如何工作的。ShardMappingsGlobal 表中有一个名为 MappingId 的列。但这不是存储在分片数据库中的 Guid/UserId。我如何获得用于识别分片的实际 Guid,在我的情况下是 UserId?我也没有找到在分片之间移动数据的方法。我现在要做的是自己使用工具在分片之间传输数据,然后使用 ListShardMap.UpdateMapping 方法为该值设置一个新的分片。在操作结束时我会使用 ListShardMap.DeleteShard 还是有更好的方法来做到这一点?

编辑:

我编写了自己的工具来合并碎片,但现在我遇到了一个奇怪的异常。这里有一些代码:

        Guid userKey = Guid.Parse(userId);
        ListShardMap<Guid> map = GetUserShardMap<Guid>();

        try
        {
            PointMapping<Guid> currentMapping = map.GetMappingForKey(userKey);

            PointMapping<Guid> mappingOffline = map.UpdateMapping(currentMapping, new PointMappingUpdate()
            {
                Status = MappingStatus.Offline
            });  
         }

UpdateMapping 导致以下异常:

存储错误:错误 515,级别 16,状态 2,过程 __ShardManagement.spBulkOperationShardMappingsLocal,第 98 行,消息:无法将值 NULL 插入 'LockOwnerId' 列,表 __ShardManagement.ShardMappingsLocal

我不明白为什么还有一个插入?我检查了本地和全局 Shardmapping 表中的 mappingId,并且映射在那里,所以我认为不需要插入。我还在这里查看了提到的存储过程 spBulkOperationShardMappingsLocal 的代码:https://github.com/Azure/elastic-db-tools/blob/master/Src/ElasticScale.Client/ShardManagement/Scripts/UpgradeShardMapManagerLocalFrom1.1To1。 2.sql 在Insert 语句中,LockOwnerId 没有作为参数传递,所以只能失败。目前我使用测试设置,因为我当然不想在生产系统上玩。也许我在那里犯了一个错误,但对我来说一切看起来都很好。对于有关此错误的任何提示,我将不胜感激。

4

1 回答 1

1

在教程中,我只找到了将 Shards 与 Range 类型合并的示例。有没有办法以更快的方式合并这些类型的分片,还是我必须为此编写自己的工具?

是的,Split-Merge 工具可以从范围和列表分片映射中移动数据。对于列表分片映射,您可以为每个键发出 shardlet 移动请求。不幸的是,Split-Merge 工具的设置有些复杂,上次我花了大约一个小时来配置。我知道这不是很好,我将由您决定是否需要更多或更少的时间来编写您自己的自定义版本。

还有一个名为 Comments 的表,其 UserId 为 ForeignKey。此表中的 PrimaryKey 是一个经典的数字自增值。如果这些值从分片 A 移动到分片 B,它们会发生什么?是否会插入它们并为它们分配一个新 ID,或者这根本不起作用?

自动增量列的值不会被复制,它们将在目的地重新生成。所以新的 id 将被分配给这些行。

为此,我查看了 ShardMapManager,但并没有完全理解它是如何工作的。ShardMappingsGlobal 表中有一个名为 MappingId 的列。但这不是存储在分片数据库中的 Guid/UserId。我如何获得用于识别分片的实际 Guid,在我的情况下是 UserId?

强烈建议不要尝试自己编辑 ShardMapManager 表,这很容易搞砸。编辑 ShardMapManager 表正是Elastic Database Tools 库的设计目的。

您可以使用方法更新映射的元数据。需要明确的是,这只会更新 ShardMapManager 表关于数据应该在哪里作为键的知识。实际上移动映射必须由更高层完成。ListShardMap.UpdatePointMapping

这是拆分合并服务所做工作的高级摘要:

  1. 锁定映射以防止来自另一个分片映射管理操作的并发更新
  2. 用 标记离线映射ListShardMap.UpdatePointMapping。这可以防止数据导向的路由OpenConnectionForKey被允许使用该密钥访问数据。它还会杀死分片上的所有当前会话以强制它们重新连接,这确保没有使用 now-offline 密钥对数据进行操作的活动连接
  3. 移动基础数据,使用 Shard MapSchemaInfo确定需要移动哪些表
  4. 更新映射并将其标记为在线ListShardMap.UpdatePointMapping
  5. 解锁映射
于 2016-09-21T19:42:02.357 回答