After one day and a half, bouncing between various resources, I finally managed to make a MongoDB Replica Set work. As it is my habit, I log my steps in a bloc-note for easy back tracking and effort saving for the future (It happens to everyone, but I get so annoyed to search twice a solution for the same problem). Those include solutions to some recurrent problems appearing down the way (and this what is special about this tutorial). I’m going to share these steps with some commentary.
Note that these are the minimum required “how-to” steps, which drove me to the final success. That said, if you want more in-depth explanations about the “what-is” part of the equation, like security considerations and performance optimizations, then, I recommend you look farther; I refer to the documentations [1] and one another interesting tutorial (that didn’t work for me for the “how-to” part) [2].
The steps are tested on a cluster of three nodes, each having Ubuntu 16.04 and MongoDB 3.6.1 installed.
- Download MongoDB as you would normally do on a single machine in each of the nodes. We recommend the tutorial on the official website: Install MongoDB.
At the end of the tutorial, you would be asked to start MongoDB server using:
1 |
sudo service mongod start |
If the service is not recognized, returning some error like: Failed to start mongodb.service: Unknown unit: mongodb.service
, then you need to enable it explicitly using:
1 |
sudo systemctl enable mongod |
Check if the server’s correctly started using:
1 |
sudo service mongod status |
- We need now to add two pieces of information to MongoDB config file: (1) the IP address of of the the node, and (2) the replica set name. Stop Mongod first:
1 |
sudo service mongod stop |
Open the config file for editing, like using vi: sudo vi /etc/mongod.conf
. Go down to net:
and set the bind IP address as a value for bindIp:
(to enable other nodes to talk to this node) . As we are creating a cluster of nodes, I recommend to omit the default localhost address 127.0.0.1 (and give less chance to errors):
1 2 3 |
net: port: 27017 bindIp: 172.180.10.160 |
Then go further down and comment out the line #replication:
. Provide the replica set name (without quotations preferably, saw people complaining from using them):
1 2 |
replication: replSetName: mongodb-rs |
Then… save.
- After that, restart MongoDB as previously:
sudo service mongod start
. - Make sure
mongod
is running in all the nodessudo service mongod status
. - Take one of the nodes, let’s say the one of IP 172.180.10.160, and run (try to avoid sudo’ing if you don’t have to):
1 |
mongo --host 172.180.10.160 |
- You need to initiate a replica set. Check first
rs.status()
if no replica set has previously been initiated (during your previous attempts), you should get a message mentioning:
1"info" : "run rs.initiate(...) if not yet done for the set" - Then run:
1rs.initiate({ _id : "mongodb-rs", members: [{_id: 0, host: "172.180.10.160:27017"}]})
you should see:{ "ok" : 1, ... }
- This adds the first node as a replica set member. Check
rs.status()
to verify that worked. - Next, add the other nodes as members to the replica set “mongodb-rs”:
1rs.add("IP_address:27017")
If that is successful, similarly,{ "ok" : 1, ... }
is shown. - Once all are added, check the status
rs.status()
, you should obtain a list of all the members; the first tagged primary:"StateStr" : "PRIMARY",
and the other SECONDARY. - Let’s give it some data and see if the replication is working. On the PRIMARY member, create a database:
use db_test
, and a collection:db.createCollection("collection_test")
, then add some data:db.collection_test.insert({"name":"test"})
. - Go to a SECONDARY member and run a read query:
use db_test
anddb.collection_test.find()
, you will supposedly be denied and obtain:not master and slaveOk=false
. To fix that run:
1rs.slaveOk()
and try again. You need to issue the latter each time you run a read query. - If that doesn’t work, make sure you are in the same database as the one used in the PRIMARY, go up in the console log and find
connecting to: P_address:27017/test
, you see here it’s the default ‘test’ database. What you need to do is to stopmongod
(Ctrl+c or another way, see [1]) and start it with the database explicitly specified, like here:
1mongo <strong>test</strong> --host 172.180.10.161
Try to find again the data again:db.collection_test.find()
, it should show up now, and you smile 🙂 because data is now correctly in sync across all the members of the replica setmongodb-rs
.
I’ll admit it, MongoDB is an awesome NOSQL database, but its preparation for big data usage is somehow less awesome. The process is a bit stressful and error-prone.
Final note: To develop a real big data application using MongoDB, the replication should be complemented with sharding, which is a topic of another post. I will try to share my experience if my time then allows.
Leave a comment