跨多个不同地理区域的 Rails/Mongo

wma*_*but 3 replication infrastructure ruby-on-rails amazon-ec2 mongodb

我有一个系统,它必然需要在三个或更多不同的位置物理存在,我需要关于以这样一种方式构建的建议,以便我的数据库保持及时复制而不会出现可怕的延迟。我已经看到当应用程序服务器试图与一个物理上没有并置的节点通信时,mysql 访问和复制非常慢。在这种情况下,我使用的是 mongodb。

  • 堆栈是 linux/passenger/ruby/rails/mongodb。
  • 数据库写重读轻。
  • 基础设施是 Amazon EC2
  • 应用层必须在物理上位于 3 个或更多不同的位置。我无法证明这个要求比它是一个要求更合理。但是,如果可以从其他位置快速写入数据库,则该数据库不必位于多个位置。

从阅读 mongo 的文档来看,mongo 复制似乎比分片 b/c 更像是一个候选者,我的数据存储并不大。但是,我没有看到任何可以解决具有潜在高延迟的远距离通信的服务器速度问题的方法。

sys*_*138 5

您的延迟体验有些令人担忧。在我自己对本地快速网络的测试中,我注意到 Mongo 和 MySQL 在延迟方面存在一些差异:

  • 对于小项目,MySQL 请求往返时间通常低于 5 毫秒。有时低至2。
  • MongoDB 请求 RTT 大约慢 3 倍,大约 15 毫秒。

部分 MongoDB 时间是由于 TCP 连接设置时间,其中 MySQL 使用预先存在的(池化)连接。在这两种情况下,数据库都没有被复制或分片,所以这些可以被认为是最好的情况(对于我的网络)。

Mongo 副本集可以在这里帮助您,但前提是您的应用程序能够容忍松散收敛1。为了获得最大速度,您必须将 mongo 写入配置为仅在 mongodb 服务器报告已收到写入时返回,并将您的应用服务器配置为仅使用 AZ 本地 Mongo 实例。读取将需要使用 SlaveOK 以便他们可以从该 AZ 本地副本读取,这将显示本地写入以及迄今为止已收敛的其他节点的复制写入。这意味着每个 AZ 对整个数据库的视图都会略有不同;过去的 X 分钟只会有局部的变化,但深层的历史会收敛。

此设置将在应用服务器和数据库服务器之间提供低(相同可用区)延迟。但是,来自应用程序服务器的数据视图将根据您的应用程序消费者访问的可用区而有所不同。这种架构是否适合您的应用程序只能由您决定。

但是,这样做有一个非常大的问题:MongoDB 不支持多主2复制,所有写入都必须到单个 Master 上。

目前 (v2.2) 无法将 MongoDB 配置为允许写入从属,因此“写重”应用程序中的所有写入都必须转到副本集的单个主控。您没有提到读取延迟是否是一个问题,但如果是,那么 SlaveOK 读取获取本地 Mongo 副本成员;但与上面不同的是,它可能还没有收到来自 master 的所有更新,所以在 write-submit 和它出现在本地 slave 之间肯定会有延迟。

Mongo 有几种不同的写类型。一旦 Mongo 服务器完全接收到写入,默认值立即返回 OK。下一步是仅在提交写入日志时才返回 OK 的模式。最偏执的(因此在带有副本的 mongo 中迄今为止最慢)仅在指定数量的副本报告写入在它们的日志中时才返回 OK 。默认模式最快,但最后一种模式确保本地副本具有写入(严格一致性)。

如果该主服务器与应用服务器不在同一个可用区中,即使使用默认写入样式,延迟对您来说也很可能无法工作。如果是这种情况,mongo 将无法为您工作,因为您的应用程序现在就存在。您将不得不认真考虑如何将应用程序更改为对写入的延迟不那么敏感,或者使用可以在松散收敛的情况下执行多主服务器的非 Mongo 数据库。

最接近多主配置的 Mongo 是通过分片。如果您的应用服务器知道它们的地理位置,您可以将地理数据包含到 Mongo Shard-Key 中。然后,当您连接到 MongoS 进行写入时,所有写入都将转到本地分片的副本集。读取可以轮询整个数据库(并且从非本地分片中提取时会相应地变慢),因此这将保持一致性。但是,这完全取决于位置是您的分片键。


1:Loose Convergence,分布式或复制数据库达到统一状态的时间就是收敛时间。松散收敛是一个很长的间隔。紧收敛是一个很短的间隔。
2:Multi-master,一种可以接受多个副本写入的数据库。可以执行此操作的数据库示例包括 Active Directory、OpenLDAP 和一些 MySQL 配置。