An Architect's View

CFML, Clojure, Software Design, Frameworks and more...

An Architect's View

Adventures in MongoDB, Part 2

June 9, 2011 ·

After my early exposure to MongoDB at the MongoSF conference on May 24th, it has come time to start exploring MongoDB more seriously. After dealing with several other database solutions, I was pleasantly surprised at how accessible the MongoDB documentation is! My target was to set up a small production-like cluster to test replication and failover.

In MongoDB-speak, what I needed to set up was a replica set and the minimum recommended production setup is either two nodes and an arbiter or three full nodes (the nodes "vote" on electing a primary instance so there needs to be an odd number). I didn't have three physical machines so I needed to set up multiple instances on a single machine. This turns out to be extremely easy with MongoDB.

Once you have MongoDB downloaded, you need to create a data folder for each instance. I'm on a Mac so I created /Developer/data1, /Developer/data2 and /Developer/data3. You also need to run each instance on a separate port so I chose 20017, 22017 and 24017. I started the three instances like this (in three separate Terminal windows):

mongod --dbpath /Developer/data1 --port 20017 --rest --replSet local
mongod --dbpath /Developer/data2 --port 22017 --rest --replSet local
mongod --dbpath /Developer/data3 --port 24017 --rest --replSet local

One issue I had was that each node has to have a separate name so I added the following entry to /etc/hosts:

127.0.0.1 mongo1 mongo2 mongo3

At this point I was able to fire up a client and get the replica set configured:

mongo --host mongo1 --port 20017
> rs.initiate()
> rs.add("mongo2:22017")
> rs.add("mongo3:24017")

At this point we can add objects to the database and they'll be replicated to the other instances - and you can read from the primary or the slaves.

> db.people.save( { name : "Sean", url : "http://corfield.org" } )
> db.people.find()

At this point you can either connect to slave and read the data:

mongo --host mongo2 --port 22017
> rs.slaveOk()
> db.people.find()

Or you can kill the primary instance and watch one of the other instances automatically take over!

Tags: mongodb

5 responses

  • 1 Bim // Jun 9, 2011 at 1:26 AM

    Great stuff Sean! What would you say is the latency say if compared to different Railo instances maintaining similar structure data in memory where each instance was keeping data in synch via <cfhttp> calls?
  • 2 Sami Hoda // Jun 9, 2011 at 9:13 AM

    That is really impressive. I've been working with SQL Server replication for 5+ years, and I can't begin to tell you how painful it is.
  • 3 John C. Bland II // Jun 9, 2011 at 9:22 AM

    This is awesome!

    So, when the primary goes down [on port 20017] and another steps up to primary did it change ports?

    I'm asking in the case where your code may point to 20017 but it died so 22017 kicks in. Do you have to change the port in your code [or domain name, IP, etc] when the failover kicks in?
  • 4 Sean Corfield // Jun 9, 2011 at 10:21 AM

    @Bim, I haven't tested replication latency but I'd expect it to be a lot faster than doing cfhttp calls between CFML servers.

    @John, you set up your connection with two or more 'seed' hosts so that the driver automatically connects you to the new primary each time. Since each host knows which nodes are up and which is the primary, the driver can adjust on the fly. You can even add new nodes on the fly and the replica set adjusts!
  • 5 John C. Bland II // Jun 9, 2011 at 10:23 AM

    Ok, that's just sick. :-)