首页 > 解决方案 > MongoDB:副本集和循环查询分布?

问题描述

我们有一个具有这种结构的 MongoDB 副本集:

我们有一个应用程序使用只读辅助节点执行非常繁重的查询。

问题是系统正在超载其中一个实例,而另外两个大多是惰性的,它们仍然接收查询,但很明显系统有一个首选实例,因此结构无法正确扩展。

这是我们的连接配置:

mongo:
  collection: "panelUsers"
  urls:
    - "mongo-001.my.network:27017"
    - "mongo-002.my.network:27017"
    - "mongo-readonly-001.my.network:27017"
    - "mongo-readonly-002.my.network:27017"
    - "mongo-readonly-003.my.network:27017"
  connection_opts:
    user: "user"
    password: "password"
    database: "mydb"
    replica_set: "mongo-replica"
    read:
      mode: "secondary"
      tag_sets:
        - nodeType: "readonly"

我可以在监视器中看到其中一个实例是如何接管大部分负载的:

在此处输入图像描述

当该过程开始时,这 3 个实例看起来它们正在占用相当一部分的查询,但随着时间的推移,其中一个实例开始占用大部分查询。当 3 个实例正常协作时,我可以看到系统性能(每分钟查询数)要好得多,当其中一个实例承担大部分负载时,整个系统开始变慢。

出于测试目的,我关闭了承担大部分负载的实例,我看到其他 2 个开始承担相当多的负载,然后系统比 3 个实例正在运行但只有一个实例承担大部分负载时更快。一段时间后,1 个实例(从左边的 2 个实例开始)开始承担所有负载,并且进程开始减慢。

我已阅读有关服务器选择算法的信息,并且我了解 Mongo 正在选择实例来解决基于 ping 延迟的查询。看起来不像一个非常进化的系统:/

我认为在我的情况下,循环机制会更好。

我可以在我们的 MongoDB 只读副本中激活循环服务器选择算法吗?

PS:我已经读过分片对我的情况来说是一个更好的解决方案,但它看起来不像我可以轻松做到的事情,在我这样做之前,我想知道是否有更简单的解决方案适合我的情况。

标签: mongodbmongodb-replica-set

解决方案


首先,MongoDB 一次只有 1 个主节点。它作为一个单一的主人工作。

所有读/写都来自主节点,除非您从辅助节点指定读取首选项。

您的“只读”辅助文件。您是否将它们配置为隐藏?因为如果发生故障转移,它们也可能成为主节点。

我的建议是执行以下操作:

  1. 保留 3 个节点的副本集(用于操作负载),而不是 5 个。为您的“常规”读写提供标准索引
  2. 有 2 个专用辅助节点(隐藏节点)用于专业负载,您可以在其中创建索引以支持您的查询
  3. 确保您没有进行集合扫描或内存排序。请参阅https://docs.mongodb.com/manual/reference/method/cursor.explain/
  4. 在副本集中拥有额外的节点并不能帮助您获得更高的读/写吞吐量,因为在主节点上写入的任何内容也会在辅助节点上写入。所以它也和初级会一样忙。但是您可以创建专家隐藏节点来支持报告负载,如 2 中所述。
  5. 分片是提高读/写吞吐量的正确方法

推荐阅读