对于MongoDB变更流读取器,什么是好的横向扩展策略?

时间:2019-01-21 17:29:20

标签: mongodb changestream

我正在考虑实现MongoDB变更流读取器,并且我想确保自己做的正确。有很多关于如何实现实际阅读器代码的简单示例,包括official documentation,而我对此并不担心。

但是,我有点担心读者落后于变更流并且无法跟上潮流,我想确保读者能够处理流程。

mongo服务器是一个群集,为了便于讨论,我们假设它在一天中的任何时候都很忙。鉴于更改流API必须迭代流结果而不是像队列一样对其进行操作,因此更改流API似乎仅与单个实例兼容。因此,我担心,与将新项目推送到流中相比,迭代实例的单个实例完成工作的时间可能更长。

我的直觉是实际上让读者简单地读取流,将更改分批处理,然后将其推入队列,然后其他工作人员可以水平扩展以完成工作。但是,作为读者,我仍然只有一个实例,即使仅做一些将修改放入队列的最小工作,它在理论上仍可能落后于潮流。

所以我的问题是,这有多么现实的担忧,并且有什么办法可以创建一种读者,即使只将更改流式传输到工作人员队列中,也可以水平扩展?我还应考虑哪些其他因素?

1 个答案:

答案 0 :(得分:0)

只需将所有工作委托给水平缩放的队列,单个阅读器就很可能满足了。

如果事实证明这还不够,而您的阅读器仍然需要水平缩放,那么您可以通过使用匹配过滤器来实现这一点,从而允许多个阅读器将工作分解。

>

例如,如果您的ID带有十六进制字符,则可以通过在每台服务器上使用match运算符将工作拆分到两台服务器上,其中每台服务器在整个范围内匹配一半字符:

// Change Stream Reader 1
const params = [
  { $match: { _id: /^[0-7]/ } }
];
const collection = db.collection('inventory');
const changeStream = collection.watch(params);

第二台机器上的

// Change Stream Reader 2
const params = [
  { $match: { _id: /^[8-9a-f]/ } }
];
const collection = db.collection('inventory');
const changeStream = collection.watch(params);

如果您需要超过16台服务器,则可以使范围更加具体:

// Server 0  matches on /^0[0-7]/
// Server 1  matches on /^1/
// ...
// Server 15 matches on /^f/
// Server 16 matches on /^0[8-9a-f]/

这将允许每台计算机查看一部分消息并进行处理,而其他计算机则在不重复的情况下处理其他消息。

以一种可靠的方式协调哪个服务器正在监视哪个范围变得有些复杂,因为您需要确保崩溃或挂起的机器恢复运行,并且如果需要水平动态扩展,则需要能够向服务器提供新范围并调整大小。此解决方案还会导致邮件处理混乱,因此,如果订购很重要,则需要提出一种解决方案,以重新排序邮件或处理乱序问题。

但是这些都是与此问题不同的主题,因此我将在此省略细节。