8

We're using amazon web service for a business application which is using node.js server and mongodb as database. Currently the node.js server is runing on a EC2 medium instance. And we're keeping our mongodb database in a separate micro instance. Now we want to deploy replica set in our mongodb database, so that if the mongodb gets locked or unavailble, we still can run our database and get data from it.

So we're trying to keep each member of the replica set in separate instances, so that we can get data from the database even if the instance of the primary memeber shuts down.

Now, I want to add load balancer in the database, so that the database works fine even in huge traffic load at a time. In that case I can read balance the database by adding slaveOK config in the replicaSet. But it'll not load balance the database if there is huge traffic load for write operation in the database.

To solve this problem I got two options till now.

Option 1: I've to shard the database and keep each shard in separate instance. And under each shard there will be a reaplica set in the same instance. But there is a problem, as the shard divides the database in multiple parts, so each shard will not keep same data within it. So if one instance shuts down, we'll not be able to access the data from the shard within that instance.

To solve this problem I'm trying to divide the database in shards and each shard will have a replicaSet in separate instances. So even if one instance shuts down, we'll not face any problem. But if we've 2 shards and each shard has 3 members in the replicaSet then I need 6 aws instances. So I think it's not the optimal solution.

Option 2: We can create a master-master configuration in the mongodb, that means all the database will be primary and all will have read/write access, but I would also like them to auto-sync with each other every so often, so they all end up being clones of each other. And all these primary databases will be in separate instance. But I don't know whether mongodb supports this structure or not.

I've not got any mongodb doc/ blog for this situation. So, please suggest me what should be the best solution for this problem.

Community
  • 1
  • 1
Indranil Mondal
  • 2,799
  • 3
  • 25
  • 40

2 Answers2

5

This won't be a complete answer by far, there is too many details and I could write an entire essay about this question as could many others however, since I don't have that kind of time to spare, I will add some commentary about what I see.

Now, I want to add load balancer in the database, so that the database works fine even in huge traffic load at a time.

Replica sets are not designed to work like that. If you wish to load balance you might in fact be looking for sharding which will allow you to do this.

Replication is for automatic failover.

In that case I can read balance the database by adding slaveOK config in the replicaSet.

Since, to stay up to date, your members will be getting just as many ops as the primary it seems like this might not help too much.

In reality instead of having one server with many connections queued you have many connections on many servers queueing for stale data since member consistency is eventual, not immediate unlike ACID technologies, however, that being said they are only eventually consistent by 32-odd ms which means they are not lagging enough to give decent throughput if the primary is loaded.

Since reads ARE concurrent you will get the same speed whether you are reading from the primary or secondary. I suppose you could delay a slave to create a pause of OPs but that would bring back massively stale data in return.

Not to mention that MongoDB is not multi-master as such you can only write to one node a time makes slaveOK not the most useful setting in the world any more and I have seen numerous times where 10gen themselves recommend you use sharding over this setting.

Option 2: We can create a master-master configuration in the mongodb,

This would require you own coding. At which point you may want to consider actually using a database that supports http://en.wikipedia.org/wiki/Multi-master_replication

This is since the speed you are looking for is most likely in fact in writes not reads as I discussed above.

Option 1: I've to shard the database and keep each shard in separate instance.

This is the recommended way but you have found the caveat with it. This is unfortunately something that remains unsolved that multi-master replication is supposed to solve, however, multi-master replication does add its own ship of plague rats to Europe itself and I would strongly recommend you do some serious research before you think as to whether MongoDB cannot currently service your needs.

You might be worrying about nothing really since the fsync queue is designed to deal with the IO bottleneck slowing down your writes as it would in SQL and reads are concurrent so if you plan your schema and working set right you should be able to get a massive amount of OPs.

There is in fact a linked question around here from a 10gen employee that is very good to read: https://stackoverflow.com/a/17459488/383478 and it shows just how much throughput MongoDB can achieve under load.

It will grow soon with the new document level locking that is already in dev branch.

Community
  • 1
  • 1
Sammaye
  • 43,242
  • 7
  • 104
  • 146
  • So, you are recommending me to go for option 1. That is shard the database and keep each replica set member of each shard in separate AWS instance. So for 2 shards with 1 primary, 3 secondary and an arbiter member needs 10 aws instances. Is that really an optimal solution? – Indranil Mondal Jul 10 '14 at 09:25
  • @Indra it is a good option, hell even spread replicas out across regions (maybe even providers) so that you have a even slimmer chance of downtime, either way you will still have a weakness somewhere unless you invest the number of members needed (yes this starts getting very big, now you can understand why fb has 32k+ database shards on MySQLs failover policy) and even then you will still find problems that means the network will need constant monitoring but the right setup does at least give you some padding – Sammaye Jul 10 '14 at 09:28
  • Yeah, I can understand. But as I have multiple instances, then in which instance we should run the mongos process and Shard Config? – Indranil Mondal Jul 10 '14 at 09:33
  • @Indra That adds on top again, you would have another 3 instances for configsrv and then you would have a set of load balanced mongos servers as well, in an ideal world – Sammaye Jul 10 '14 at 09:35
  • But I think keeping the configsrv in a single instance may cause problem if the instance is unavailable. Is it possible to keep the configsrv in each instance where we've a replicaset member? So that which instace is available, we'll get the primary member of each shard as well as the configsrv. – Indranil Mondal Jul 10 '14 at 09:43
  • @Indra that's why you have 3 configsrvs, also remember that the mongos does not always connect with configsrvs, it caches the information from the config so a configsrv going down isn't a major problem. – Sammaye Jul 10 '14 at 09:46
  • Oh really! "the mongos does not always connect with configsrvs, it caches the information from the config so a configsrv going down isn't a major problem" is a new thing to me. I was not aware of that. So I can run three config servers in three instances, so if one instance shuts down it'll not cause any problem. – Indranil Mondal Jul 10 '14 at 09:53
  • @Indra not immediately, the cache does refresh every...10 minutes I think it is currently, also even with 1 down you still got 2 configs – Sammaye Jul 10 '14 at 09:56
  • Yeah, got it. That's why I said to keep the config server in multiple instances. – Indranil Mondal Jul 10 '14 at 10:08
  • @Indra exactly, even though it can run on the same instance as another the configsrvs should all be on their own small servers (micros will do it on aws) spread out. Yeah I don't think you got anything to worry about with the mongos/configsrv side of things – Sammaye Jul 10 '14 at 10:11
2

Option 1 is the recommended way as pointed out by @Sammaye but you would not need 6 instances and can manage it with 4 instances.

Assuming you need below configuration.

  • 2 shards (S1, S2)
  • 1 copy for each shard (Replica set secondary) (RS1, RS2)
  • 1 Arbiter for each shard (RA1, RA2)

You could then divide your server configuration like below.

Instance 1 : Runs : S1 (Primary Node)
Instance 2 : Runs : S2 (Primary Node)
Instance 3 : Runs : RS1 (Secondary Node S1) and RA2 (Arbiter Node S2)
Instance 4 : Runs : RS2 (Secondary Node S2) and RA1 (Arbiter Node S1)

You could run arbiter nodes along with your secondary nodes which would help you in election during fail-overs.

Lalit Agarwal
  • 2,354
  • 1
  • 14
  • 18
  • But it'll not solve the problem. Suppose if instance 4 shuts down, then we'll have only the primary of S2 active, it'll not have any other replicaset member. Though it's very rare case that a Amazon instance shuts down. But I want to handle that situation. Actually I want to add 3 secondary and a arbitor in each replicaset. So in this situation I need 10 instances for only 2 shards. – Indranil Mondal Jul 10 '14 at 09:17
  • @Indra there will always be a weakness somewhere, whether it is in failover potential or inconsistent data and sets, you will find that this is a bottomless pit – Sammaye Jul 10 '14 at 09:24
  • Yeah, actually I'm confused about which one is the best solution, that's why I need you people's suggestions. – Indranil Mondal Jul 10 '14 at 09:28
  • @Indra personally I consider that option 1 is best but I am a MongoDB guy, I am biased. I am even more biased since I have never used multi-master replication personally. I mean your logic is sound and even though we have added a bit here at the end of the day this is something that will come down to you, we can give you pointers and help you decide but we cannot tell you the best solution, it is too subjective and opinionated. – Sammaye Jul 10 '14 at 09:33
  • 1
    @Indra if instance 4 goes down then primary of S2 and Arbiter of S2 (Instance 3) will be live. Also, goes down is not forever right, it should come up again and when that happens your data would be re-synced from primary to secondary. – Lalit Agarwal Jul 10 '14 at 09:37
  • @Sammaye yeah I can understand that it's hard to say which one in best solution as it's too subjective. But this discussion is really very helpful for me to decide, which one is better. – Indranil Mondal Jul 10 '14 at 09:47
  • @LalitAgarwal Yeah, that's true. It's really very very rare case that two instances will be shut down at same time. – Indranil Mondal Jul 10 '14 at 09:48
  • I will say the only problem to running multipole mongods on the same instance is of resource contention. You could very quickly see them fighting for memory space and IO unless you contain with docker or vmware or something – Sammaye Jul 10 '14 at 09:54
  • @Sammaye No, I'll not run multiple mongods in same instance. But as I've 1 primary, 3 secondary and an arbitor. I'll keep the primary, and two secondary in separate instance. And the secondary of the replica of shard1 and the arbitor of the replica of shard2 in another instance. Because as Lalit said, I don't need to keep the arbitor in separate instance. – Indranil Mondal Jul 10 '14 at 10:05
  • @Indra ok kool, yeah I misread his answer sorry, I thought I saw two secondaries on RS1 but I was just being stupid – Sammaye Jul 10 '14 at 10:09
  • @Sammaye I tried to deploy option 1 with 4 machines locally connected to test, but getting some error to connect mongos. I've added another question http://stackoverflow.com/questions/24684940/error-to-connect-mongos-when-trying-to-create-replicated-sharded-cluster to show what I've done yet. Please help me. – Indranil Mondal Jul 10 '14 at 19:44
  • @Sammaye I've added an new question and given the link in my previous comment. I'm not being able to deploy sharding in multiple instance.Please help. – Indranil Mondal Jul 11 '14 at 07:09