在 Azure 中管理多租户存储的最有效方式?

Most effective way to manage multiple tenant storage in Azure?

我们正在创建一个多租户应用程序,它必须在租户之间隔离数据。每个租户都会保存各种文档,每个文档都可以分为几个不同的文档类别。我们计划为这些文档使用 Azure blob 存储。但是,考虑到我们的用户群以及文档的数量和每个文档的大小,我们不确定如何使用当前的 Azure 订阅最好地管理存储帐户。

这里有一些数字需要考虑。 5,000 个用户,每个用户每年 27,000 个 8Mb 文档,即每年总计 1080TB。每个存储帐户的存储容器最大容量为 500TB。

所以我的问题是存储这些数据并保持在 Azure 限制内的最有效和最具成本效益的方法是什么?

以下是我们考虑的一些事项:

  1. 为每个客户端创建一个存储帐户。这不起作用,因为每个订阅只能有 100 个存储帐户(这本来是最理想的解决方案)。

  2. 为每个客户端创建一个 blob 容器。一个存储帐户最多可以有 500TB,所以这可能会起作用,除非最终我们不得不拆分成其他存储帐户。如果最终用户在两个帐户中拥有数据,我不确定这将如何工作。可能会变得凌乱。

也许我们在这里遗漏了一些基本简单的东西。

更新 目前我们的想法是使用 Azure table 存储,每个文档类型都有一个 table。在每个 table 中,分区键是租户的 ID,行键是文档 ID。每行还将包含文档的元数据类型信息,以及链接到 blob 本身的 URI(或其他内容)。

不是真正的答案,但可以将其视为 "food for thought" :)。基本上,您的体系结构应该基于这样一个事实,即每个存储帐户都有一些 scalability targets,并且您的设计应该不会超过这些以保持应用程序存储的高可用性。

一些建议:

  • 首先创建多个存储帐户(比如 10 个)。我们称他们为 Pods.
  • 每个租户将获得一个吊舱。您可以随机选择一个 pod 存储帐户或使用一些预定义的逻辑。有关 Pod 的信息与租户信息一起存储。
  • 从描述来看,目前您似乎只将文件信息存储在一个 table 中。这会给一个 table/storage 帐户带来很大压力,恕我直言,这不是可扩展的设计。相反,在创建租户时,您将一个 pod 分配给租户,然后为每个租户创建一个 table,它将文件信息存储在 table 中。这将有以下好处:1) 您很好地隔离了每个租户数据,2) 读取请求现在是负载平衡的,因此允许您保持在可伸缩性目标内,以及 3) 由于每个租户数据位于单独的 table ,您的 PartitionKey 变得免费,您可以根据需要分配其他值。

现在开始存储文件:

  • 您可以再次使用 Pod 概念,其中每个租户的文件驻留在该租户的 pod 存储帐户中。
  • 如果您发现此方法存在问题,您可以随机选择 pod 存储帐户并将文件放在那里并将 blob URL 存储在 Files table.
  • 您可以只使用一个 blob 容器(比如 tenant-files),也可以为每个租户使用单独的 blob 容器。
  • 所有租户只有一个 blob 容器,管理开销较小,因为您只需在委托新的 pod 时创建此容器。然而,缺点是您无法按租户在逻辑上分隔文件,因此如果您想提供对文件的直接访问(使用共享访问签名),那将是有问题的。
  • 每个租户使用单独的 blob 容器,管理开销更多,但您可以获得很好的逻辑隔离。在这种情况下,当租户加入时,您必须在每个 pod 存储帐户中为该租户创建容器。同样,当新的 pod 被委托时,您必须确保为系统中的每个租户创建一个 blob 容器。

希望这能让您对如何构建解决方案有所了解。我们在我们的解决方案中使用了其中一些概念(明确使用 Azure 存储作为数据存储)。看看你想出什么样的架构真的很有趣。

我只是想谈谈我对这个话题的看法,它确实有一些与 Gaurav Mantri 的回答有关的冗余信息。这是基于我在当前工作中做了非常相似的事情后想出的设计。

Azure Blob 存储

  1. 创建租户时从pod pool随机select一个pod并将其命名空间与租户信息一起存储。

  2. 提供一个 api 用于创建容器,其中容器名称由租户 ID Guid::ToString("N") + <resourcename> 组成。您不需要将其作为容器出售给您的用户,我可以是文件夹、工作集或文件箱,您可以找到一个名称。

  3. 提供 api 用于维护这些容器中的文档。

这意味着如果有更多租户,您可以增加 pod pool,删除那些 pods 正在被填满的人。

这样做的好处是您不需要为数据保留两个系统,同时使用 table 存储和 blob 存储。 Blob 存储已经可以将数据呈现为 directory/files 层次结构。

扩展点

Blob 存储Api代理

在上述设计之上,我制作了一个包裹在客户端和 blob 存储之间的 Owin 中间件,基本上只是将来自客户端的请求转发到 blob 存储。 由于不需要,此步骤已关闭,因为您可以委托普通的 sas 令牌并直接与来自客户端的 blob 存储对话。但是当对文件执行操作时,它可以很容易地挂钩。每个租户将获得自己的端点 files/teantid/<resourcename>/

使用这样的 API 还可以让您连接到您可能已经使用的任何令牌身份验证系统,以验证身份验证和授权传入请求,然后在此 API 中签署请求.

Blob 存储元数据

使用上面的 api 代理扩展,结合元数据,实际上可以更进一步,修改传入请求以始终包含元数据,并在返回到 blob 存储的 xml 上添加过滤器在将其发送给客户端以过滤掉容器或 blob 之前。一个例子是当用户删除一个 blob,然后设置 x-ms-meta-status:deleted 并在返回 blobs/containers 时过滤掉它们。这样您就可以添加不同的程序来在后台删除数据。

这里应该小心,因为你不想在这里放太多逻辑,因为它会增加对所有请求的惩罚,但巧妙地处理可以使这项工作非常好。

此扩展还允许您允许您的用户在容器内创建“空”子文件夹,但放置一个带有 status:hidden 的零字节文件也将被过滤掉。 (请记住,只有在虚拟文件夹中有内容时,blob 存储才能显示它们)。这也可以使用 table 存储来实现。

Azure 搜索

另一个重要的扩展点是,对于每个 blob,您可以将其保存在 Azure 搜索中以便能够找到内容,这很可能是我最喜欢的。我没有看到任何好的解决方案仅使用 blob 存储或 table 存储可以为您提供良好的搜索功能或在某种程度上什至提供良好的过滤体验。借助 Azure 搜索,这将为用户提供真正丰富的再次查找内容的体验。

快照

另一个扩展是可以为每次文件自动修改创建快照。使用代理 api,这变得更加容易,否则监控日志是一个选项。

这些想法来自我开始的一个项目,我想分享,但由于接下来几个月我的工作很忙,我认为自己不会在暑假给我时间完成之前发布我的项目。该项目的动机是提供一个 nuget 包,使其他开发人员能够快速设置我上面提到的这个代理 api 并配置多租户 blob 存储解决方案。

如果您阅读本文并相信这样的项目可以在您当前的开发过程中节省时间,我恳请您为这个答案投票。这样我就可以看看我是否可以在项目上花费更多时间。

我认为 gaurav Mantris 对上述问题的回答更准确,但只是想分享我对这个主题的看法。