代码之家  ›  专栏  ›  技术社区  ›  justin.m.chase

MongoDB变更流阅读器的水平缩放策略是什么?

  •  1
  • justin.m.chase  · 技术社区  · 6 年前

    我正在考虑实现MongoDB变更流阅读器,我想确保我做的正确。关于如何实现实际的阅读器代码,有很多简单的例子,包括 official documentation 我不太担心这方面。

    不过,我有点担心读者 落在后面 无法赶上的变更流,我想确保读者能够处理该流。

    Mongo服务器是一个集群,我们假设它在一天中的任何时候都非常繁忙。变更流API似乎只与执行工作的单个实例兼容,因为它必须迭代流结果,而不是像队列一样对其进行操作。因此,我担心迭代结果的单个实例可能比将新项推送到流中花费更长的时间来完成其工作。

    我的直觉是让读者简单地阅读流,批处理更改,然后将其推到一个队列中,在这个队列中其他工作人员可以水平伸缩来完成工作。然而,我仍然有一个作为读者的单一实例,理论上它仍然有可能落在流后面,即使只做将变更推入队列的最少的工作。

    所以我的问题是,这是一个多么现实的担忧,有没有任何方法来创建这样一个读者,它可以横向扩展,即使它只是将更改流到一个工作队列?我还应考虑哪些其他因素?

    1 回复  |  直到 6 年前
        1
  •  0
  •   justin.m.chase    6 年前

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

    如果结果证明这是不够的,并且您的读者仍然需要水平缩放,那么您可以通过使用匹配过滤器来实现这一点,这样可以让多个读者将工作分开。

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

    // 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]/
    

    这将允许每台计算机监视消息的一个子集并对其进行处理,而其他计算机则在不重复地处理其他消息。

    协调哪个服务器正在以一种健壮的方式监视哪个范围变得有些复杂,因为您需要确保崩溃或挂起的机器恢复,如果您需要动态地水平缩放,那么您需要能够向服务器提供新的范围并调整其大小。此解决方案还将导致消息处理无序,因此,如果顺序很重要,则需要为重新排序消息或处理无序问题提出解决方案。

    但这些都是和这个问题不同的主题,所以我暂时不谈细节。