是否有一种解决方案允许从猫鼬中完全相同的快照中读取多个集合?
Posted
技术标签:
【中文标题】是否有一种解决方案允许从猫鼬中完全相同的快照中读取多个集合?【英文标题】:Is there a solution which allows to read from multiple collections from the exact same snapshot in mongoose? 【发布时间】:2021-05-03 14:08:32 【问题描述】:让我解释一下我的问题,这不太可能发生,但可能发生。
我有两个集合,A 和 B。B 是 A 的“孩子” - 所以 A 有一个字段 b_id
。我想阅读 A,它的 B 孩子处于一致的状态。我担心的是:
A (in state 0) read
B changed (from state 0 to state 1)
B (in state 1) read
我想要的是:
A (in state 0) read
B changed (from state 0 to state 1)
B (in state 0) read
为了帮助想象,一旦我开始读取“过程”,我希望有一个一致的数据库“快照”,所以即使在读取 A 和B,我会以开始阅读时的状态阅读B。
这很难测试,所以它更像是一个理论问题。我正在做关于填充、聚合的研究,但感觉即使这些方法都是按顺序工作的,所以在上述情况下它有可能会失败,但我不知道。哪种方法(如果存在)可以解决上述问题?
【问题讨论】:
【参考方案1】:简短的回答是否定的。
Mongo 不保留数据的历史值,一旦文档更新,除非您设置延迟辅助,否则无法读取其先前版本。
有交易和快照,但它们针对不同的问题,对您的情况没有帮助。
您可以通过使用$lookup 聚合在同一个查询中查询两个集合来最大限度地减少读取两个集合之间的时间。它不保证集合 B 中的文档在查询期间不会更改,但会显着缩短从 2 个集合读取之间的时间,因此读取更新版本的机会将大大减少。
如果不够好,例如如果您的整个业务都依赖此保证,或者如果好人因这种读取不一致而死亡,您将需要在应用程序级别实现它。
我头顶有2个选项。
使用修改时间戳。确保这些时间戳在任何数据修改时单调更新,例如与$currentDate。在查询时获取第一个查询之前的当前时间戳并将其添加到两个查询的过滤器中,以便在此之后修改的文档不会匹配过滤器。您将需要实现查询后验证逻辑以检查空响应是因为根本没有此类文档还是因为它已更新,重试读取等。
第二个选项是依靠change streams 将文档的“最近状态”保存在更改流客户端中 - 一种将集合 B 中更新文档的历史记录保存一段时间的服务。在此设置中,您无需更改文档结构或查询中的任何内容,但向此更改流服务发出验证请求以确认没有更改并且您的读取是一致的。
后者的设置要复杂一些,您需要考虑更改流的时间延迟。前者更简单,更可靠,只要所有写入数据库正确更新修改时间戳。
【讨论】:
以上是关于是否有一种解决方案允许从猫鼬中完全相同的快照中读取多个集合?的主要内容,如果未能解决你的问题,请参考以下文章