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

How reliable is change stream support in Azure Cosmos DB’s API for MongoDB?

描述

我正在开发一个 ASP.NET Core 3.1 Web 应用程序,它需要 track/respond 对 Azure Cosmos DB(版本 3.6)托管的 MongoDB 数据库所做的更改。 为此,我使用 Change feed support.

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

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

private async Task HandleChangeStreamAsync<T>(IMongoCollection<T> coll, StreamWriter file, CancellationToken cancellationToken = default)
{
    var pipeline = new EmptyPipelineDefinition<ChangeStreamDocument<T>>()
            .Match(change => change.OperationType == ChangeStreamOperationType.Insert || 
                             change.OperationType == ChangeStreamOperationType.Update || 
                             change.OperationType == ChangeStreamOperationType.Replace)
            .AppendStage<ChangeStreamDocument<T>, ChangeStreamDocument<T>, ChangeStreamOutputWrapper<T>>(
                  "{ $project: { '_id': 1, 'fullDocument': 1, 'ns': 1, 'documentKey': 1 }}");

    var options = new ChangeStreamOptions
    {
        FullDocument = ChangeStreamFullDocumentOption.UpdateLookup
    };

    using (var cursor = await coll.WatchAsync(pipeline, options, cancellationToken))
    {
        await cursor.ForEachAsync(async change =>
        {
            var json = change.fullDocument.ToJson(new JsonWriterSettings { Indent = true });
            await file.WriteLineAsync(json);
        }, cancellationToken);
    }
}

问题

在观察输出时,我注意到对集合进行的每次更新都不会触发更改源。我可以通过将生成的输出与 MongoDB Cloud.

托管的数据库进行比较来确认这一点

问题

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

  2. API能否保证总是有最新的更新?

  3. 我自己无法处理 'local' 数据库的 'oplog.rs' 集合,API 是否以任何方式支持它?这甚至受到鼓励吗?

  4. 收集吞吐量 (RU/s) 在某种程度上与更改事件频率有关吗?

最后的想法

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

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

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

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

How reliable is change stream support in Azure Cosmos DB’s API for MongoDB?

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

更改提要的限制之一是它可以“批量”更新。在内部,更改提要处理器轮询更改提要,它将获取所有已更改的项目。但是,如果一个项目在民意调查之间多次更改,它只会在更改源中显示一次。这是 Cosmos DB SQL API Change Feed 的行为,我希望同样的限制适用于 MongoDB 更改流,尽管我没有看到它实际记录在MongoDB 文档。

另一个限制是没有观察到删除。

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

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

Can the API guarantee that the most recent update will always be available?

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

I was not able to process the 'oplog.rs' collection of the 'local' database on my own, does the API support this in any way? Is this even encouraged?

¯\(ツ)

Is the collection throughput (RU/s) in some way related to the change event frequency?

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

My understanding is that frequent updates throttle the system and the change feed simply does not handle all of the events from the log (rather scans it periodically).

没错。

However, I am wondering how safe it is to rely on such mechanism and be sure not to miss any critical updates made to the database.

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

switching to polling would greatly affect the performance and would lead to a solution which is not scalable.

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