问题描述
说明
我正在开发一个 ASP.NET Core 3.1 Web 应用程序,该应用程序需要跟踪/响应对 Azure Cosmos DB(3.6 版)托管的 MongoDB 数据库所做的更改。 为此,我使用了 Change feed support。
更改非常频繁:集合中的单个条目每秒更新约 10 次。
为了追踪对集合所做的更改,我将受影响的条目转储到一个文件中(这仅用于测试目的),其中包含以下内容代码。
@JsonProperty
问题
在观察输出时,我注意到对集合所做的每次更新都不会触发更改提要。我可以通过将生成的输出与 MongoDB Cloud 托管的数据库进行比较来确认这一点。
问题
-
Azure Cosmos DB 的 MongoDB API 中的变更流支持有多可靠?
-
API 能否保证最新的更新始终可用?
-
收集吞吐量 (RU/s) 是否与更改事件频率有关?
最后的想法
我的理解是,频繁的更新会限制系统,并且更改提要根本无法处理日志中的所有事件(而是定期对其进行扫描)。 但是,我想知道依赖这种机制有多安全,并且确保不会错过对数据库所做的任何关键更新。如果更改提要支持无法对事件处理频率做出任何保证,并且无法处理“oplog.rs”,那么唯一的选择似乎是定期轮询数据库。
如果我错了,请纠正我,但切换到轮询会极大地影响性能并导致解决方案不可扩展。
解决方法
我怀疑 MongoDB 更改流是基于 Cosmos DB 更改源构建的。我的经验完全与 Cosmos DB 更改提要有关;我根本没有使用过 MongoDB API。所以这个答案都是假设 MongoDB 更改流在内部使用 Cosmos DB 更改提要,这是有道理的,但我可能是错的。
Azure Cosmos DB 的 MongoDB API 中的变更流支持有多可靠?
它完全可靠,但有一些限制。
更改提要限制之一是它可以“批量”更新。在内部,更改提要处理器轮询更改提要,它将获取所有已更改的项目。但是,如果某个项目在投票之间多次更改,则它只会在更改提要中显示一次。这是 Cosmos DB SQL API 更改源的行为,我希望同样的限制适用于 MongoDB 更改流,但我没有看到它在 MongoDB 文档中的任何地方实际记录。
另一个限制是不观察删除。
由于这些限制,变更源/变更流不是事件溯源解决方案。如果您想要事件溯源,那么您需要自己将数据建模为事件;没有任何内置功能可以为您做到这一点。
也就是说,在这些限制范围内,您的代码将接收更改提要中的每个更改文档,这是完全可靠的。限制只是意味着多个更新可能会作为单个更改的文档出现,而删除的文档根本不会出现。
API 能否保证最新的更新始终可用?
在您的代码从更改提要中检索文档后,文档总是有可能发生更改,在这种情况下,更新后的文档将重新发布到更改提要中,您的代码稍后会再次看到它。不能保证(当然)您的代码刚刚从更改提要中获得的文档与数据库中的文档相同,但最终会保持一致。
我无法自行处理“本地”数据库的“oplog.rs”集合,API 是否以任何方式支持此操作?这甚至受到鼓励吗?
¯\(ツ)/¯
收集吞吐量 (RU/s) 是否与更改事件频率有关?
是的。更改提要本身内置于 Cosmos DB,但更改提要处理具有 RU 成本。更改提要处理器使用 RU 轮询更改提要、从更改提要读取文档,并更新其“书签”以跟踪更改提要中的位置。
我的理解是,频繁的更新会限制系统,并且更改提要根本无法处理日志中的所有事件(而是定期对其进行扫描)。
没错。
然而,我想知道依赖这种机制有多安全,并且确保不会错过对数据库所做的任何关键更新。
代码将始终(最终)接收更新的文档。但是,如果您需要单独查看每个更改,那么您将需要使用诸如事件溯源之类的东西来构建您的数据。如果您的应用程序只关心文档的最终状态,那么更改提要就可以了。但是,例如,如果您需要知道 someCriticalProperty
是否设置为 true
然后返回到 false
,那么您将需要事件溯源。
切换到轮询会极大地影响性能,并且会导致解决方案不可扩展。
投票不一定是坏事。更改提要处理器使用轮询,如上所述。它还具有允许横向扩展的巧妙机制,其中不同的处理器可以查看同一个集合,可以在它们之间拆分文档(通过分区键);我不确定这是否/如何转化为 MongoDB 世界,但它是一个非常优雅的解决方案,用于扩展 SQL API 更改提要处理器,并且与 Azure Functions 配合得很好(不幸的是,Azure Functions 没有 MongoDB 更改流触发器)。