【问题标题】:Meteor: Efficient way to iterate over ALL users server-sideMeteor:在服务器端迭代所有用户的有效方法
【发布时间】:2017-12-01 08:40:43
【问题描述】:

在我的 Meteor 应用中,用户可以互相关注。当一个用户关注另一个用户时,需要在 MongoDB 上运行多个操作,因此关注操作本身并不是完全原子的。如果服务器在执行过程中崩溃,用户个人资料上的虚荣计数表示他或她关注了多少用户,即"following": 24 实际上可能与您在 MongoDB 的followers 集合中直接查找的数量不匹配存储关系数据。

为了缓解这种情况,假设每 24 小时,在午夜,我安排了一个 cron 作业,它在 MongoDB 中查找每个 user 文档,并根据其他集合中的数据验证文档的完整性。如果用户文档中的数据准确无误,则为noop,然后继续下一个用户文档。如果有任何计数不正确,请更正它们,然后再继续下一个用户。

我的问题是:您如何有效地实施这种 CRON 工作?假设我在 Meteor 应用上有 100,000 个注册用户。如果我执行Meteor.users.find().fetch(),我什至会在开始迭代之前将 100k 用户文档加载到 RAM 中。随着用户群的增长,问题会更加复杂,这感觉就像等待发生的服务器崩溃。

什么是确保所有用户文档都得到处理的最佳方法,同时有效地处理,而不是完全锁定 Meteor 服务器,以便它仍然可以响应来自 Web 前端的用户请求?

【问题讨论】:

    标签: meteor


    【解决方案1】:

    假设我在 Meteor 应用上有 100,000 个注册用户。如果我做了一个 Meteor.users.find().fetch(),我会将 100k 用户文档加载到 在我开始迭代之前的 RAM。

    有两点。

    首先,您可以通过在 find 方法中使用投影来减少加载的数据:

    db.collection.find(query, projection)
    

    https://docs.mongodb.com/manual/reference/method/db.collection.find/

    此投影包含与您相关的字段的名称。 Mongo 只会返回游标,包含具有这些字段的文档。这可能会将数据量减少到最低限度。

    一个例子是:

    Meteor.users.find({},{following:1).fetch()
    

    此查询查找“所有”用户,但仅返回他们的文档,其中包含“以下”字段。

    第二件事。

    调用 .find().fetch() 会将您的 mongo 光标转换为一个数组,您必须逐步迭代此数组。

    由于您在服务器 cli 上工作(您可以将 mongo 的 api 发挥到最大),您可能宁愿在光标级别上工作。它提供了很多方法来迭代和操作数据:

    https://docs.mongodb.com/manual/reference/method/js-cursor/

    第三件事:

    不管你是使用游标还是数组(获取)解决方案:你可以尝试实现一个延迟加载机制。因此,您可能只处理大量新文档,而不是整个队列。因此,您保证始终有空间 (RAM) 用于其他东西。

    https://en.wikipedia.org/wiki/Lazy_loading

    如果您对这些建议有任何疑问,请告诉我。

    【讨论】:

    • 酷,看起来 cursor.forEach() 可能会有所帮助。您如何建议在流星中分块加载用户文档?
    • 一种可能的方法是为每个用户分配一个字段,例如当新用户插入集合时,调用'index'并增加字段值。然后你可以通过索引字段和$gt和$lt加载一定数量的用户。如果您说您加载 10 个用户的块,您将加载所有索引 >= 0 和 = 10 和
    • 如果遇到困难,您当然可以详细说明自己的解决方案并在此处发布一个新问题。 :-)
    猜你喜欢
    • 1970-01-01
    • 2014-08-20
    • 1970-01-01
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-14
    • 2017-06-25
    相关资源
    最近更新 更多