Azure Cosmos DB 的 MongoDB API 中的变更流支持有多可靠?

iva*_*zan 3 azure mongodb azure-cosmosdb azure-cosmosdb-mongoapi azure-cosmosdb-changefeed

描述

\n

我正在开发一个 ASP.NET Core 3.1 Web 应用程序,该应用程序需要跟踪/响应对 Azure Cosmos DB(版本 3.6)托管的 MongoDB 数据库所做的更改。\n为此,我使用更改源支持

\n

更改非常频繁:集合中的单个条目每秒约更新 10 次。

\n

为了跟踪对集合所做的更改,我将受影响的条目转储到文件中(这仅用于测试目的使用以下代码

\n
private async Task HandleChangeStreamAsync<T>(IMongoCollection<T> coll, StreamWriter file, CancellationToken cancellationToken = default)\n{\n    var pipeline = new EmptyPipelineDefinition<ChangeStreamDocument<T>>()\n            .Match(change => change.OperationType == ChangeStreamOperationType.Insert || \n                             change.OperationType == ChangeStreamOperationType.Update || \n                             change.OperationType == ChangeStreamOperationType.Replace)\n            .AppendStage<ChangeStreamDocument<T>, ChangeStreamDocument<T>, ChangeStreamOutputWrapper<T>>(\n                  "{ $project: { \'_id\': 1, \'fullDocument\': 1, \'ns\': 1, \'documentKey\': 1 }}");\n\n    var options = new ChangeStreamOptions\n    {\n        FullDocument = ChangeStreamFullDocumentOption.UpdateLookup\n    };\n\n    using (var cursor = await coll.WatchAsync(pipeline, options, cancellationToken))\n    {\n        await cursor.ForEachAsync(async change =>\n        {\n            var json = change.fullDocument.ToJson(new JsonWriterSettings { Indent = true });\n            await file.WriteLineAsync(json);\n        }, cancellationToken);\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

问题

\n

在观察输出时,我注意到对集合进行的每次更新都不会触发更改源。我可以通过将生成的输出与 MongoDB Cloud 托管的数据库进行比较来确认这一点。

\n

问题

\n
    \n
  1. 适用于 MongoDB 的 Azure Cosmos DB\xe2\x80\x99s API 中的更改流支持有多可靠?

    \n
  2. \n
  3. API能否保证最新的更新始终可用?

    \n
  4. \n
  5. 我无法自行处理“本地”数据库的“oplog.rs”集合,API 是否以任何方式支持此操作?这还被鼓励吗?

    \n
  6. \n
  7. 收集吞吐量 (RU/s) 是否在某种程度上与更改事件频率相关?

    \n
  8. \n
\n

最后的想法

\n我的理解是,频繁的更新会限制系统,并且更改源根本不处理日志中的所有事件(而是定期扫描日志)。\n但是,我想知道依赖这种机制有多安全,并确保不要错过对数据库所做的任何关键更新。\n
\n

如果更改源支持无法对事件处理频率做出任何保证,并且无法处理“oplog.rs”,则唯一的选择似乎是定期轮询数据库。

\n

如果我错了,请纠正我,但切换到轮询会极大地影响性能,并会导致解决方案不可扩展。

\n

Ste*_*ary 8

我怀疑 MongoDB 更改流是基于 Cosmos DB 更改源构建的。我的经验完全来自于 Cosmos DB 更改源;我根本没有使用过 MongoDB API。所以这个答案都是假设 MongoDB 更改流内部使用 Cosmos DB 更改源,这是有道理的,但我可能是错的。

\n
\n

适用于 MongoDB 的 Azure Cosmos DB\xe2\x80\x99s API 中的更改流支持有多可靠?

\n
\n

它完全可靠,但有一些局限性。

\n

更改源的限制之一是它可以“批量”更新。在内部,更改源处理器轮询更改源,它将获取所有已更改的项目。但是,如果某个项目在轮询之间多次更改,则它只会在更改源中显示一次。这是 Cosmos DB SQL API 更改源的行为,我预计同样的限制也适用于 MongoDB 更改流,尽管我没有看到它在 MongoDB 文档中的任何地方实际记录。

\n

另一个限制是无法观察到删除。

\n

由于这些限制,变更源/变更流不是事件溯源解决方案。如果您想要事件溯源,那么您需要自己将数据建模为事件;没有任何内置功能可以为您做到这一点。

\n

也就是说,在这些限制内,它是完全可靠的,因为您的代码将接收更改源中的每个更改的文档。这些限制仅意味着多个更新可能会作为单个更改的文档出现,而删除的文档根本不会出现。

\n
\n

API能否保证最新的更新始终可用?

\n
\n

在您的代码从更改源检索文档后,文档总是有可能发生更改,在这种情况下,更新的文档将重新发布到更改源,并且您的代码稍后会再次看到它。(当然)不能保证您的代码刚刚从更改源获取的文档与数据库中的文档相同,但它最终会保持一致。

\n
\n

我无法自行处理“本地”数据库的“oplog.rs”集合,API 是否以任何方式支持此操作?这还被鼓励吗?

\n
\n

\xc2\xaf\\ (\xe3\x83\x84) /\xc2\xaf

\n
\n

收集吞吐量 (RU/s) 是否在某种程度上与更改事件频率相关?

\n
\n

是的。更改源本身内置于 Cosmos DB 中,但更改源处理会产生 RU 成本。更改源处理器使用 RU 来轮询更改源、从更改源读取文档以及更新其“书签”以跟踪它在更改源中的位置。

\n
\n

我的理解是,频繁的更新会限制系统,并且更改源根本不处理日志中的所有事件(而是定期扫描日志)。

\n
\n

那是对的。

\n
\n

但是,我想知道依赖这种机制有多安全,并确保不要错过对数据库所做的任何关键更新。

\n
\n

代码将始终(最终)收到更新的文档。但是,如果您需要单独查看每个更改,那么您将需要使用事件源之类的方法来构建数据。如果您的应用程序只关心文档的最终状态,那么更改源就可以了。但是,例如,如果您需要知道是否someCriticalProperty设置true为然后返回到false,那么您将需要事件溯源。

\n
\n

切换到轮询会极大地影响性能,并且会导致解决方案不可扩展。

\n
\n

民意调查不一定是坏事。如上所述,变更馈送处理器使用轮询。它还具有允许横向扩展的巧妙机制,其中观察同一集合的不同处理器可以在它们之间分割文档(通过分区键);我不确定这是否/如何转化为 MongoDB 世界,但它是一个非常优雅的解决方案,用于扩展 SQL API 更改源处理器,并且与 Azure Functions 配合得很好(不幸的是,Azure Functions 没有 MongoDB 更改流触发器)。

\n