How to read from both members of my Replica Set

86 views
Skip to first unread message

Tom DeMille

unread,
Nov 7, 2012, 11:54:36 AM11/7/12
to mongodb...@googlegroups.com
Have a 3 node replica set, where one node is an Arbiter.  Thus at any one time I have a primary and secondary server.  I would like to allow my application to read from either one, in fact I would love to 'load balance' the load somehow.

Whats the best way to achieve this?    If the primary is running 'slow' will the driver automatically read from the secondary, thus achieving a true 'load' based balance?

What would the c# code/connection strings look like to accomplish this.  It seems this has changed over the past year and 1/2 and I want to check in for the latest greatest best practices.

I'm using 2.2.1 Mongo.

I will be updating c# driver to latest version.

Tom DeMille

unread,
Nov 7, 2012, 11:56:26 AM11/7/12
to mongodb...@googlegroups.com
Check that, we can't upgrade the driver right now, using 1.4.2

Robert Stam

unread,
Nov 7, 2012, 12:16:20 PM11/7/12
to mongodb...@googlegroups.com
In version 1.4.2 the only setting available to you is slaveOk=true or false.

If you set slaveOk=true your reads will go to the secondary. If you set slaveOk=false your reads will go to the primary. There is no way to get the driver to load balance between them. You could of course do the load balancing yourself by alternately setting slaveOk to false or true to distribute the reads.

Once you upgrade to 1.6.1 you and use the new ReadPreference setting, which replaces slaveOk and has more values:

Primary (equivalent to slaveOk=false)
PrimaryPreferred
Secondary
SecondaryPreferred (equivalent to slaveOk=true)
Nearest

Seems like Nearest would do what you want, distributing the reads between the primary and secondary. Note that Nearest load balances evenly (in other words, it doesn't measure the load, it just evenly distributes the reads among all eligible servers).

Tom DeMille

unread,
Nov 7, 2012, 1:56:19 PM11/7/12
to mongodb...@googlegroups.com
Thanks Robert.  

A moment ago my new secondary switched to Primary (because I configured it incorrectly with priority 2).  When this happened my web applications started failing with "Server is not a primary and SlaveOk is false." errors.

I understand that in one respect, in that we are NOT using slaveOK.  But what I don't understand is why my web application, via the c# driver,  didn't just 'find' the new primary via discovery from Mongo.  

Does the c# driver cache the replication stuff?  Would I need to do an IISRESET or blow away my application pools in order to get the replication information that I just recently setup?  My understanding has been that the c# driver should have known about the 3 servers in my cluster, even though I didn't specifically add the new IP to my connection string, and automatically have found the new primary.


Here is my current (obscured) connect string : mongodb://xxx.xxx.xxx.xxx/?maxpoolsize=200;waitqueuemultiple=5.0;waitqueuetimeout=120s

Tom

Robert Stam

unread,
Nov 7, 2012, 2:02:54 PM11/7/12
to mongodb...@googlegroups.com
You only have one server on the connection string?

If so, that implies a direct connection without using replica set discovery behavior.

You can either use a more complete seed list (minimum of two) or add "connect=replicaSet" or "replica=xyz", where xyz is the name of your replica set, to get replica set behavior.

Even with replica set behavior, there are a couple of things to keep in mind. First is that the driver does not guarantee you won't see any exceptions, just that it will switch over to the new primary as soon as it can. During the period that the election is taking place (and there is no primary) you are pretty much guaranteed to get exceptions. Second, the smoothness with which the driver tracks changes in the state of the replica set members has been improving, so yet another reason that you should upgrade from 1.4.2 when you can.

Tom DeMille

unread,
Nov 8, 2012, 9:29:09 AM11/8/12
to mongodb...@googlegroups.com
Thanks Robert,

Regardless of the driver version, can I just pass these settings through on a global connection string?     

Something like :    

mongodb://xxx.xxx.xxx.xxx/, xxx.xxx.xxx.xx1?replica=foo;mode=nearest;

If so, could you point me to the correct format, been searching can't find anything specifically about this.

t

Robert Stam

unread,
Nov 8, 2012, 10:36:21 AM11/8/12
to mongodb...@googlegroups.com
You have a slash in the wrong place. The correct syntax is:

mongodb://xxx.xxx.xxx.xxx,xxx.xxx.xxx.xxx/?replicaSet=foo

There is no connection string option called "mode".

In 1.6.1 you can use "readPreference" on the connection string:

mongodb://xxx.xxx.xxx.xxx,xxx.xxx.xxx.xxx/?replicaSet=foo;readPreference=nearest

But not in earlier versions because ReadPreference was added in 1.6.

The connection string format (for all drivers) is document at:


Although it hasn't been updated to reflect the new ReadPreference options.

Tom DeMille

unread,
Nov 8, 2012, 10:40:52 AM11/8/12
to mongodb...@googlegroups.com
Ok, so the readPreference is not a server function but rather the driver needs to know how to correctly respond to that connection string and handle the connection details on the client side?    I was incorrectly thinking it would just pass it through and the server would manage the replication details.

thanks Robert.

Robert Stam

unread,
Nov 8, 2012, 10:46:21 AM11/8/12
to mongodb...@googlegroups.com
Yes, the driver is the one choosing which member of a replica set to talk to.

It's a little different when talking to a sharded cluster through mongos, but in in your case it looks like you are connecting to a replica set, not a sharded cluster.

John Woakes

unread,
Nov 13, 2012, 12:55:44 AM11/13/12
to mongodb...@googlegroups.com
Hi Robert,

Have you considered creating a setting that would wait if an election is in progress when trying to issue an update command? It is a pain to have that period when the replica set is "down" when a wait would be pretty seamless for the very few times this happens. We are running in Azure so our servers do go down. Replica sets should protect us from this with out failing writes if possible.

John.

Robert Stam

unread,
Nov 13, 2012, 8:45:49 PM11/13/12
to mongodb...@googlegroups.com
There have been various proposals for the driver to handle more retries automatically, but it's hard to determine what the right course of action is. What's right for one user might not be what's right for another.

That's why the current philosophy is that it's up to the application to decide:

1. Whether to retry a failed operation
2. How many times to retry a failed operation
3. For how much time to retry a failed operation

The time component is specially critical. We don't want a call to the driver to block indefinitely if the primary is down or if an election is taking an unusually long time to complete.

Nik Kolev

unread,
Nov 14, 2012, 10:05:29 AM11/14/12
to mongodb...@googlegroups.com
How about making this part of the MongoServer configuration? The default behavior could be left as it is right now - no retries. But if the user would like the driver to handle retries it could configure the MongoServer instance to do that (with number of retries, max elapsed time before timeout, perhaps a retry strategy - "constant retry", "consistent wait", backoff, etc.). 

Sridhar Nanjundeswaran

unread,
Nov 14, 2012, 10:15:35 AM11/14/12
to mongodb...@googlegroups.com
We also need to consider the corner case of when majority of the nodes are down. So in this case there will be no primary node elected till there is some intervention to bring up a quorum.
--
  name     : "Sridhar Nanjundeswaran", 
  title    : "Software Engineer",
  twitter  : ["@snanjund", "@MongoDB""@10gen"]
}

 


Reply all
Reply to author
Forward
0 new messages