【问题标题】:MongoDB load balancing in multiple AWS instances多个 AWS 实例中的 MongoDB 负载平衡
【发布时间】:2014-08-31 12:19:13
【问题描述】:

我们将亚马逊网络服务用于使用 node.js 服务器和 mongodb 作为数据库的业务应用程序。目前 node.js 服务器在 EC2 中型实例上运行。我们将 mongodb 数据库保存在一个单独的微实例中。现在我们想在我们的 mongodb 数据库中部署副本集,这样如果 mongodb 被锁定或不可用,我们仍然可以运行我们的数据库并从中获取数据。

所以我们试图将副本集的每个成员保存在单独的实例中,这样即使主成员的实例关闭,我们也可以从数据库中获取数据。

现在,我想在数据库中添加负载均衡器,这样数据库即使在一次巨大的流量负载下也能正常工作。在这种情况下,我可以通过在副本集中添加 slaveOK 配置来读取数据库平衡。但是如果数据库中写入操作的流量负载很大,它就不会对数据库进行负载均衡。

为了解决这个问题,到目前为止我有两个选择。

选项 1:我必须对数据库进行分片并将每个分片保存在单独的实例中。并且在每个分片下都会有一个副本集在同一个实例中。但是有一个问题,因为分片将数据库分成多个部分,所以每个分片不会在其中保存相同的数据。因此,如果一个实例关闭,我们将无法访问该实例内分片中的数据。

为了解决这个问题,我尝试将数据库划分为分片,每个分片在不同的实例中都有一个副本集。因此,即使一个实例关闭,我们也不会遇到任何问题。但是如果我们有 2 个分片并且每个分片在副本集中有 3 个成员,那么我需要 6 个 aws 实例。所以我认为这不是最佳解决方案。

选项 2:我们可以在 mongodb 中创建一个 master-master 配置,这意味着所有数据库都将是主数据库并且都将具有读/写访问权限,但我也希望它们彼此自动同步通常,所以它们最终都是彼此的克隆。所有这些主数据库都将位于单独的实例中。但是不知道mongodb是否支持这种结构。

对于这种情况,我没有任何 mongodb 文档/博客。所以,请建议我什么应该是这个问题的最佳解决方案。

【问题讨论】:

    标签: mongodb amazon-web-services amazon-ec2 load-balancing database


    【解决方案1】:

    到目前为止,这还不是一个完整的答案,细节太多了,我可以像其他许多人一样写一篇关于这个问题的完整文章,但是因为我没有那种空闲时间,我会添加一些关于我所看到的评论。

    现在,我想在数据库中添加负载均衡器,以便数据库在一次巨大的流量负载下也能正常工作。

    副本集的设计并非如此。如果您希望负载平衡,您实际上可能正在寻找允许您执行此操作的分片。

    复制用于自动故障转移。

    在这种情况下,我可以通过在副本集中添加 slaveOK 配置来读取平衡数据库。

    因为,为了保持最新状态,您的成员将获得与主要成员一样多的操作,这似乎没有太大帮助。

    实际上,不是让一台服务器排队有许多连接,而是在许多服务器上排队等待陈旧数据,因为成员一致性是最终的,而不是像 ACID 技术那样立即生效,但据说它们最终只有 32-奇数毫秒,这意味着如果加载主节点,它们的延迟不足以提供不错的吞吐量。

    由于读取是并发的,因此无论您是从主数据库还是辅助数据库读取,您都将获得相同的速度。我想您可以延迟从站以创建 OP 暂停,但这会带来大量陈旧的数据作为回报。

    更不用说 MongoDB 不是多主节点,因为您一次只能写入一个节点,这使得 slaveOK 不再是世界上最有用的设置,而且我已经多次看到 10gen 自己建议您使用分片这个设置。

    方案2:我们可以在mongodb中创建master-master配置,

    这需要您自己编码。此时您可能要考虑实际使用支持http://en.wikipedia.org/wiki/Multi-master_replication的数据库

    这是因为您正在寻找的速度实际上很可能是写入而不是读取,正如我上面讨论的那样。

    选项 1:我必须对数据库进行分片并将每个分片保存在单独的实例中。

    这是推荐的方法,但您已经发现了它的警告。不幸的是,多主复制应该解决的问题仍未解决,但是,多主复制确实将自己的瘟疫老鼠船添加到欧洲本身,我强烈建议您在考虑是否进行认真研究之前MongoDB 目前无法满足您的需求。

    您可能真的什么都不担心,因为 fsync 队列旨在处理 IO 瓶颈,这会减慢您的写入速度,就像在 SQL 中一样,并且读取是并发的,因此如果您正确规划架构和工作集,您应该能够获得大量的 OP。

    事实上,这里有一个来自 10gen 员工的相关问题,非常值得阅读:https://stackoverflow.com/a/17459488/383478,它显示了 MongoDB 在负载下可以实现多少吞吐量。

    随着新的文档级别锁定已经在 dev 分支中,它将很快增长。

    【讨论】:

    • 所以,您建议我选择选项 1。即对数据库进行分片并将每个分片的每个副本集成员保存在单独的 AWS 实例中。因此,对于具有 1 个主分片、3 个辅助分片和一个仲裁成员的 2 个分片,需要 10 个 aws 实例。这真的是最佳解决方案吗?
    • @Indra 这是一个不错的选择,地狱甚至将副本分散到各个区域(甚至可能是提供者),这样您停机的机会就更小了,无论哪种方式,除非您投资所需的成员数量(是的,这开始变得非常大,现在您可以理解为什么 fb 在 MySQL 故障转移策略上拥有 32k+ 数据库分片)即使这样您仍然会发现问题意味着网络需要持续监控,但正确的设置确实如此至少给你一些填充
    • 是的,我能理解。但是由于我有多个实例,那么我们应该在哪个实例中运行 mongos 进程和 Shard Config?
    • @Indra 再次补充,在理想情况下,您将拥有另外 3 个 configsrv 实例,然后您还将拥有一组负载平衡的 mongos 服务器
    • 但我认为如果实例不可用,将 configsrv 保存在单个实例中可能会导致问题。是否可以在我们拥有副本集成员的每个实例中保留 configsrv?因此,哪个实例可用,我们将获取每个分片的主要成员以及 configsrv。
    【解决方案2】:

    选项 1 是 @Sammaye 指出的推荐方式,但您不需要 6 个实例,可以使用 4 个实例来管理它。

    假设您需要以下配置。

    • 2 个分片(S1、S2)
    • 每个分片1个副本(副本集辅助)(RS1,RS2)
    • 每个分片(RA1、RA2)1 个仲裁器

    然后你可以像下面这样划分你的服务器配置。

    Instance 1 : Runs : S1 (Primary Node)
    Instance 2 : Runs : S2 (Primary Node)
    Instance 3 : Runs : RS1 (Secondary Node S1) and RA2 (Arbiter Node S2)
    Instance 4 : Runs : RS2 (Secondary Node S2) and RA1 (Arbiter Node S1)
    

    您可以与辅助节点一起运行仲裁节点,这将帮助您在故障转移期间进行选举。

    【讨论】:

    • 但这并不能解决问题。假设如果实例 4 关闭,那么我们将只有 S2 的主节点处于活动状态,它不会有任何其他副本集成员。尽管亚马逊实例关闭的情况非常罕见。但我想处理这种情况。实际上我想在每个副本集中添加 3 个辅助和一个仲裁器。所以在这种情况下,我只需要 2 个分片的 10 个实例。
    • @Indra 总会有一个弱点,无论是潜在的故障转移还是不一致的数据和集合,你会发现这是一个无底洞
    • 是的,实际上我很困惑哪个是最好的解决方案,这就是为什么我需要你们的建议。
    • @Indra 我个人认为选项 1 是最好的,但我是 MongoDB 人,我有偏见。由于我个人从未使用过多主复制,因此我更加偏颇。我的意思是您的逻辑是合理的,即使我们在一天结束时在这里添加了一些内容,这将归结为您,我们可以为您提供指导并帮助您做出决定,但我们无法告诉您最佳解决方案,它过于主观和固执己见。
    • @Indra 如果实例 4 发生故障,则 S2 的主节点和 S2 的仲裁器(实例 3)将处于活动状态。此外,宕机并非永远正确,它应该再次出现,当这种情况发生时,您的数据将从主服务器重新同步到辅助服务器。
    猜你喜欢
    • 1970-01-01
    • 2018-09-05
    • 1970-01-01
    • 2017-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多