ruby-on-railsmongodbruby-on-rails-4mongoidmoped

Mongoid preferred read replica


I'm building a geo redundant MongoDB replica set, but there is a problem. Every time a query is sent to the database apparently a random replica is choosen.

MOPED: x.x.x.0:p COMMAND      database=admin command={:ismaster=>1} runtime: 148.4439ms
MOPED: x.x.x.1:p COMMAND      database=admin command={:ismaster=>1} runtime: 150.5547ms
MOPED: x.x.x.2:p COMMAND      database=admin command={:ismaster=>1} runtime: 3.8707ms
MOPED: x.x.x.3:p COMMAND      database=admin command={:ismaster=>1} runtime: 289.3072ms

As you can see the third replica is the nearest, so it would be a waste of time to read from another one, but that's what happens:

MOPED: x.x.x.3:p QUERY        database=d collection=c selector={} flags=[:slave_ok] limit=-1 skip=0 batch_size=nil fields=nil runtime: 393.3878ms

So the question is, can I specify the IP address of the preferred read, or just tell MOPED to connect to the fastest one?

The mongoid.yml file now specifies all 4 replicas:

  hosts:
    - x.x.x.0:p
    - x.x.x.1:p
    - x.x.x.2:p
    - x.x.x.3:p
  options:
    read: :secondary

One option would be to just manually set only the master, and the nearest replica:

  hosts:
    - x.x.x.0:p
    - x.x.x.2:p
  options:
    read: :secondary

But I don't feel is a good solution as availability would suffer in case of failures.


Solution

  • Figured out, reading this: https://github.com/mongoid/moped/blob/master/lib/moped/read_preference.rb you can see that moped supports reading from the nearest replica, so the solution is very simple, in mongoid.yml:

    hosts:
      - x.x.x.0:p
      - x.x.x.2:p
    options:
      read: :nearest