Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prefer reads on secondaries in MongoDb

When using mongodb in a replica set configuration (1 arbiter, 1 primary, 2 slaves); how do I set a preference that read be performed against the secondaries and leave the primary only for writes? I'm using MongoDb 2.0.4 with Morphia. I see that there is a slaveOk() method, but I'm not sure how that works.

Morphia http://code.google.com/p/morphia/

Details My Mongo is set with the following options:

mongo.slaveOk();
mongo.setWriteConcern(WriteConcern.SAFE);

I am attempting to use the following (this may be answer -btw):

Datastore ds = getDatastore();
Query<MyEntity> query = ds.find(MyEntity.class).field("entityId").equal(entityId);
query.queryNonPrimary(); // appears equivalent to ReadPrefererence.secondary()
MyEntity entity = query.get();
like image 638
Paul Gregoire Avatar asked Jan 29 '13 16:01

Paul Gregoire


People also ask

How do I change the read preference in MongoDB?

You must call Mongo. setReadPref() on the connection object before retrieving documents using that connection to use that read preference. To apply a read preference for a specific query or queries, you can apply cursor. readPref() to a cursor before iteration.

How do I query secondary in MongoDB?

By calling rs. slaveOk() you are indicating to the system that you acknowledge that reads will be eventually consistent and wish to be able to query the secondary anyway. Following the principle of self-documenting code, rs. slaveOk() should really be called rs.

Which read Preference mode allows a secondary to be the only choice for handling read operations on a MongoDB replica set?

Starting in version 4.4, primaryPreferred supports hedged reads on sharded clusters. Operations read only from the secondary members of the set. If no secondaries are available, then this read operation produces an error or exception.


2 Answers

The correct answer, after much blood and sweat is as follows:

  • To prefer all reads / queries hit the secondaries, only slaveOk() need be set
  • To prefer only selected reads use secondaries, do not set slaveOk() and use queryNonPrimary() instead per query

It is also a good practice to set an appropriate write concern when using replica sets, like so:

mongo.setWriteConcern(WriteConcern.REPLICAS_SAFE);
like image 176
Paul Gregoire Avatar answered Sep 21 '22 14:09

Paul Gregoire


It seems that the current method (as per Java driver 2.8+) is to do

MongoOptions options = new MongoOptions();
options.setReadPreference(ReadPreference.secondaryPreferred());

then

mongo = new com.mongodb.Mongo(Arrays.asList(address1, address2), options);

This will make all connections prefer using secondaries, but will use the primary as a backup if the secondary is down or unavailable for some reason.

like image 37
Nic Cottrell Avatar answered Sep 19 '22 14:09

Nic Cottrell