Pour configurer le jeu de répliques, j'ai exécuté dans 3 onglets de terminal distincts:
$ Sudo mongod --replSet rs0 --dbpath /data/mining --port 27017
$ Sudo mongod --replSet rs0 --dbpath /data/mining2 --port 27018
$ Sudo mongod --replSet rs0 --dbpath /data/mining3 --port 27019
Ensuite, j'ai configuré la réplication dans le Mongo Shell et vérifié que cela fonctionnait:
> var rsconf = {
_id: "rs0",
members: [
{
_id: 0,
Host: 'localhost:27017'
},
{
_id: 1,
Host: 'localhost:27018'
},
{
_id: 2,
Host: 'localhost:27019'
}
]
};
> rs.initiate(rsconf);
{
"info": "Config now saved locally. Should come online in about a minute.",
"ok": 1
}
// Some time later...
> rs.status()
{
"set": "rs0",
"date": ISODate("2013-06-17T13:23:45-0400"),
"myState": 2,
"syncingTo": "localhost:27017",
"members": [
{
"_id": 0,
"name": "localhost:27017",
"health": 1,
"state": 1,
"stateStr": "PRIMARY",
"uptime": 4582,
"optime": {
"t": 1371489546,
"i": 1
},
"optimeDate": ISODate("2013-06-17T13:19:06-0400"),
"lastHeartbeat": ISODate("2013-06-17T13:23:44-0400"),
"lastHeartbeatRecv": ISODate("2013-06-17T13:23:44-0400"),
"pingMs": 0
},
{
"_id": 1,
"name": "localhost:27018",
"health": 1,
"state": 2,
"stateStr": "SECONDARY",
"uptime": 5034,
"optime": {
"t": 1371489546,
"i": 1
},
"optimeDate": ISODate("2013-06-17T13:19:06-0400"),
"self": true
},
{
"_id": 2,
"name": "localhost:27019",
"health": 1,
"state": 2,
"stateStr": "SECONDARY",
"uptime": 4582,
"optime": {
"t": 1371489546,
"i": 1
},
"optimeDate": ISODate("2013-06-17T13:19:06-0400"),
"lastHeartbeat": ISODate("2013-06-17T13:23:44-0400"),
"lastHeartbeatRecv": ISODate("2013-06-17T13:23:45-0400"),
"pingMs": 0,
"syncingTo": "localhost:27017"
}
],
"ok": 1
}
Mon script fonctionne bien contre le primaire:
$ ./runScripts.sh -h localhost -p 27017
MongoDB Shell version: 2.4.3
connecting to: localhost:27017/test
Successful completion
Cependant, contre l'un ou l'autre secondaire:
$ ./runScripts.sh -h localhost -p 27018
MongoDB Shell version: 2.4.3
connecting to: localhost:27017/test
Mon Jun 17 13:30:22.989 JavaScript execution failed: count failed:
{ "note" : "from execCommand", "ok" : 0, "errmsg" : "not master" }
at src/mongo/Shell/query.js:L180
failed to load: /.../.../myAggregateScript.js
J'ai lu à plusieurs endroits pour utiliser rs.slaveOk()
ou db.getMongo().setSlaveOk()
, mais aucun de ceux-ci n'a eu d'effet, qu'il soit entré à partir du shell ou appelé dans mon script. Ces instructions n'ont pas généré d'erreurs lors de leur appel, mais elles n'ont pas non plus résolu le problème.
Quelqu'un sait-il pourquoi je ne peux pas configurer mon replset pour autoriser l'interrogation du secondaire?
rs.slaveOk()
exécuté dans le shell mongo vous permettra de lire à partir des secondaires. Voici une démonstration utilisant le mongo Shell sous MongoDB 2.4.3:
$ mongo --port 27017
MongoDB Shell version: 2.4.3
connecting to: 127.0.0.1:27017/test
replset:PRIMARY> db.foo.save({})
replset:PRIMARY> db.foo.find()
{ "_id" : ObjectId("51bf5dbd473d5e80fc095b17") }
replset:PRIMARY> exit
$ mongo --port 27018
MongoDB Shell version: 2.4.3
connecting to: 127.0.0.1:27018/test
replset:SECONDARY> db.foo.find()
error: { "$err" : "not master and slaveOk=false", "code" : 13435 }
replset:SECONDARY> rs.slaveOk()
replset:SECONDARY> db.foo.find()
{ "_id" : ObjectId("51bf5dbd473d5e80fc095b17") }
replset:SECONDARY> db.foo.count()
1
Vous devez exécuter la commande rs.slaveOk()
dans le shell du serveur secondaire.