[JAVA-889] Query not going to secondary with a slaveDelay Created: 18/Jul/13  Updated: 04/Dec/13  Resolved: 06/Aug/13

Status: Closed
Project: Java Driver
Component/s: Query Operations
Affects Version/s: 2.9.3
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Michael Champagne Assignee: Justin Lee
Resolution: Done Votes: 0
Labels: query, read-preferences, replicaset, slaveOk
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Windows, java7



 Description   

I am using Morphia 0.99.1-SNAPSHOT with 2.9.3 mongodb java driver.

I have a replica set with one master and one slave. I want to use the slave for all reads, because to master will be busy enough with writes. The 60 seconds delay is there only so that I can validate my reads are really goind to the secondary (I will remove the delay in production).

Here is the configuration of my replica set :

rs.conf()

{
    "_id" : "rsStat",
    "version" : 3,
    "members" : [
        {
            "_id" : 0,
            "host" : "someDNS:27024",
            "priority" : 2
        },
        {
            "_id" : 1,
            "host" : "someDNS:27025",
            "priority" : 0,
            "slaveDelay" : 60
        }
    ]
}

Here is my java code :

MyClass.java

Morphia morphia = new Morphia();
String host = "someDNS";
int port = 27024;
String dbName = "someDatabaseName";
 
// Configure the mongo options
MongoOptions options = new MongoOptions();
options.autoConnectRetry = true;
options.connectionsPerHost = 100;
options.w = WriteConcern.NONE.getW();
options.readPreference = ReadPreference.secondaryPreferred();
// options.slaveOk = true;
 
// Declare the real Mongo object
Mongo mongo;
 
// Look at the system.replset collection to know the replica set status
Mongo mongoInit = new Mongo(new ServerAddress(host, port), options);
DB localDb = mongoInit.getDB("local");
DBCollection replsetCollection = localDb.getCollection("system.replset");
DBObject replsetInfos = replsetCollection.findOne();
 
// If the returned object is null, there is no replica set (a single node)
if (replsetInfos == null)
{
	mongo = new Mongo(new ServerAddress(host, port), options);
}
else
{
	// It's a replica set, gather information of each node
	List<ServerAddress> addresses = getReplicaSetInfos(host, replsetInfos);
 
	// The Mongo constructor doesn't work with a list of only one address...
	if (addresses.size() > 1)
	{
		mongo = new Mongo(addresses, options);
	}
	else
	{
		mongo = new Mongo(addresses.get(0), options);
	}
}
 
// Create the morphia datastore
Datastore datastore = morphia.createDatastore(mongo, dbName);
datastore.getMongo().setReadPreference(ReadPreference.secondaryPreferred());
 
morphia.mapPackage("some.package");
 
datastore.ensureIndexes();
 
List<SomeDocument> docs = datastore.find(SomeDocument.class).queryNonPrimary().asList();
 

So, I'm doing a modification on the primary, changing a value in a document from "A" to "B". Few seconds later, I run a find() on the secondary in the mongo shell and I still see "A". Few seconds later, I run this java code and I get "B", the new value. Why is that?

It looks like my reads are going to the primary : if I would have read from the secondary, I would get the "A" value.
I'm setting the read preference to secondaryPreferred.
I'm adding the queryNonPrimay().
I think it's a bug that my read isn't going to the secondary.

Is this bug fixed in a later version?



 Comments   
Comment by Michael Champagne [ 06/Aug/13 ]

okay thanks

Comment by Justin Lee [ 06/Aug/13 ]

The statement "when reading from a secondary, a query may return data that reflect a previous state" refers to the case where the sync between the primary and a secondary lags for whatever reason.

Comment by Michael Champagne [ 06/Aug/13 ]

I didn't know that we CAN'T read from delayed secondaries. I thought that we could read from them in cases where we don't mind having inconsistent data. Thanks for the reply.

Still, can you explain the "when reading from a secondary, a query may return data that reflect a previous state" to me? see http://docs.mongodb.org/manual/applications/replication/

Finally, I'd like to edit the title of this issue for "Query not going to delayed secondary". Can you do it?

Comment by Justin Lee [ 06/Aug/13 ]

Michael, after some digging I can verify that queries do hit the secondary without the slaveDelay. If you watch the logs, you can see the query show up in the secondary logs. By design, slave-delayed secondaries do not report as members of the replica set to the driver so reads against will always fail because the data can't help but be inconsistent.

Comment by Michael Champagne [ 19/Jul/13 ]

I did more tests, and I see that my queries are going to the secondary if I remove the delay. Is this normal? I mean, why can't I have full control over where my queries go?

Comment by Michael Champagne [ 19/Jul/13 ]

http://docs.mongodb.org/manual/applications/replication/

"If clients configure the read preference to permit secondary reads, read operations cannot return from secondary members that have not replicated more recent updates or operations. When reading from a secondary, a query may return data that reflects a previous state."

Hmm, this is confusing... We can't read from secondary members not up-to-date, BUT when reading from a secondary, a query may return data that reflect a previous state.

Comment by Michael Champagne [ 18/Jul/13 ]

I have to mention that both primay and secondary databases are on the same machine (for now), so the latency is the same.

Generated at Thu Feb 08 08:53:18 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.