【问题标题】:Generating shard key field for multi tenant mongodb app为多租户 mongodb 应用程序生成分片键字段
【发布时间】:2014-10-18 22:59:54
【问题描述】:

我正在开发一个在 mongodb 上运行的多租户应用程序。每个租户可以创建多个应用程序。大多数集合的架构通过 ObjectID 引用其他集合。我正在考虑使用以下格式手动创建一个分片键:

(v3 murmurhash of the record's ObjectId) + (app_id.toHexString())

这是否足以确保任何特定应用程序的记录最终都可能在同一个分片上?

此外,如果某个特定应用程序与分片上的所有其他应用程序相比变得超大,会发生什么情况?

【问题讨论】:

    标签: mongodb mongoose sharding


    【解决方案1】:

    如果您使用基于散列的分片键并且输入不断变化(ObjectID 通常可以被认为对于每条记录都是唯一的),那么您将根本无法获得分片上的数据局部性(巧合除外),尽管它会通过在所有分片上随机分布写入来为您提供出色的写入吞吐量。这基本上是这种方法的权衡,内置hash based sharding也是如此,这些权衡不会因为它是由两个字段构成的手动哈希而改变。

    基本上,因为 MongoDB 使用基于范围的块来拆分给定分片键的数据,在这种情况下,您将使用连续的哈希范围作为块。假设您的哈希在某种程度上没有错误,那么单个顺序范围内的数据基本上是随机的。因此,即使在单个块中,您也没有数据局部性,更不用说在分片上,它将是完全随机的(根据设计)。

    如果您希望能够将应用程序按范围分组在一起,从而更有可能位于特定分片上,那么您最好预先添加 app_id 以使其成为复合分片键中最左侧的字段.像下面这样的分片将(基于有限的描述)是一个好的开始:

    {app_id : 1, _id : 1}
    

    尽管 ObjectID 会随着时间的推移单调增加(更多关于 here 的讨论),但如果有相当数量的应用程序 ID 并且您要对 ObjectID 执行任何基于范围或有针对性的查询,那么它可能不过仍然可以正常工作。您可能还希望根据您的查询模式包含其他字段。

    请记住,无论您最常见的查询模式是什么,您都希望分片键(理想情况下)尽可能满足它。它必须被索引,它已被mongos 用来决定路由查询(如果没有,那么它是scatter/gather),所以如果你要不断地查询app_id_id 那么上面的分片键很有意义。

    如果您使用手动散列密钥方法,您不仅会有随机分布,而且除非您要查询该散列,否则它不会很有用。

    【讨论】:

    • 感谢您的详细解答!最初我的意思是我不会对 app_id 进行散列,只是将其附加到行的 _id 的散列中,但指出不需要生成我自己的散列并让 mongo 处理它。
    • 还有几个问题。 1) 如果没有为每条记录填充 app_id,会不会有问题?具体来说,我允许创建可以在多个应用程序之间共享的租户级别文档。 2) 将tenant_id 添加到分片键哈希是否有缺点?例如:{tenant_id: 1, app_id:1, _id: 1}?这样做的目的是本地化租户文档,即使它们不属于 app_id。
    • 这可能是一种有效的方法——尽管你可能不想让它成为一个稀疏索引(以防万一你想这样做)。问题是所有未填充的字段将组合在一个分片上,因此如果没有 app_id 的流量很大,您可能会有一个热点。两个 ID 的组合,特别是如果始终填充最左边的键,对于未填充的 app_id 会有所不同,并且包含在查询中将是更好的选择。与往常一样,如果可能,测试将是一个验证的好主意。
    • 我明白了,为了讨论,我们假设 app_id 将始终被填充。由于 app_id 和 _id 都是 ObjectId,它们都是单调递增的,这种策略会导致分片之间的写入分布不佳。是否可以选择一个分片键,将相关的 app_id 组合在一起,但也可以在分片子集之间随机写入。几乎就像松散的本地化一样,特定 app_id 的记录将随机分成几个(但不是全部)分片?
    • 我要看的一件事(当然取决于唯一性/时间戳要求)是如何生成您的 ObjectID。它们导致写入扩展性较差的分片键的原因是最高有效位是时间戳,并且在自动生成时会随着时间自动增加。但是,您可以手动生成并避免该问题。如果这不是一个选项,那么您正在寻找具有一些粗糙度的复合键 - 目前是否有一个字段可以满足这种松散的选择性?如果没有,那么您可能需要自己创建
    猜你喜欢
    • 2021-06-14
    • 2014-02-15
    • 2021-03-31
    • 2018-08-29
    • 2011-05-05
    • 2015-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多