Do we need replicaSet in connection URI of MongoDB - mongodb

When connecting to mongo cluster do we need replicaSet option in connection URI like below
mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test
What happens if replicaSet option is not used but all the nodes are given in connection URI like below
mongodb://db1.example.net:27017,db2.example.net:2500/
What is the advantage of giving and not giving replicaSet in the connection URI for the above 2 cases.

It's always recommended to include the replicaSet in the MongoDB connection String URI Format as a best practice. Enabling this will help to explore much more options for better application connectivity.
Advantages of including replicaSet:
Once enabled the client/driver will be aware of the all other members in the replica set.
If fail-over occurs client/driver automatically connects to next available member with zero downtime.
Using readConcern we can scale the reads better with other replica members.
replicaSet=myRepl&readConcernLevel=majority
To acknowledge all the write operation we can use write concern along with the URI
replicaSet=myRepl&w=majority&wtimeoutMS=5000
We can enable the connection timeout to maintain a better connectivity.
replicaSet=test&connectTimeoutMS=200000
Securing the application to use only TLS/SSL encrypted connections.
replicaSet=myRepl&ssl=true
For better secured application support and connectivity always use the replicaSet on connection String URI.

You should specify also the replicaSet.
If you don't specify the replicaSet then you still connect to the PRIMARY node. However, in case the PRIMARY becomes unavailable then your connection is lost. If you specify the replicaSet then the client will automatically re-connect to the new primary member.
You an play around and make test with these commands:
db.hello().primary returns the current primary member
db.hostInfo().system.hostname returns the member where you are currently connected to

if you have an endpoint like: mongodb+srv://username:password#mycluster.mik05g.mongodb.net
run the nslookup CLI
nslookup -type=TXT mycluster.mik05g.mongodb.net
Server: 127.0.0.53
Address: 127.0.0.53#53
Non-authoritative answer:
mycluster.mik05g.mongodb.net text = "authSource=admin&replicaSet=MyCluster-shard-0"
So the replicaSet name here is: MyCluster-shard-0

Related

How to connect to a specifc node in a mongo replica set?

I use mongo connection uri string to connect to my mongo.
mongodb+srv://myname:mypass#mydb.mongodb.net/myDb?retryWrites=true&w=majority
This replica set has 4 nodes. I wish to execute my read operation on a specifc node. I have the node url. But I am not sure where I should specify this in the connection uri. I could not find anything regarding this in the connection-options for connection uri.
This can be done using the readPreferenceTags. The node that I wanted to connect to had a tag with key nodeType and a value analytics. So my connection uri had to be modified to
mongodb+srv://myname:mypass#mydb.mongodb.net/myDb?retryWrites=true&w=majority&readPreference=secondary&readPreferenceTags=nodeType:ANALYTICS

MongoDB error not master and slaveOk=false

I am using MongoDB with Loopback in my application with a loopback connector to the MongoDB. My application was working fine but now it throws an error
not master and slaveOk=false.
try running rs.slaveOk() in a mongoDB shell
You are attempting to connect to secondary replica whilst previously your app (connection) was set to connect likely to the primary, hence the error. If you use rs.secondaryOk() (slaveOk is deprecated now) you will possibly solve the connection problem but it might not be what you want.
To make sure you are doing the right thing, think if you want to connect to the secondary replica instead of primary. Usually, it's not what you want.
If you have permissions to amend the replica configuration
I suggest to connect using MongoDB Compass and execute rs.status() first to see the existing state and configuration for the cluster. Then, verify which replica is primary.
If necessary, adjust priorities in the replicaset configuration to assign primary status to the right replica. The highest priority number sets the replica as primary. This article shows how to do it right.
If you aren't able to change the replica configuration
Try a few things:
make sure your hostname points to the primary replica
if it is a local environment issue - make sure you added your local replica hostnames to the /etc/hosts pointing to 127.0.0.1
experiment with directConnection=true
experiment with multiple replica hosts and ?replicaSet=<name> - read this article (switch tabs to replica)
The best bet is that your database configuration has changed and your connection string no longer reflects it correctly. Usually, slight adjustments in the connection string are needed or just checking to what instance you want to connect.

Mongo: How to automatically connect to secondary in case of primary failure

I have a replica of three mongod instances, one of them is the primary instance, and the other two are secondary. I connected a mongo instance to the primary, and then I turned off the mongod primary instance, simulating a failure.
Typically, as soon as I initiated a command, mongo generated a DBClientCursor::init call() failed error.
My question is, in case of such a failure, where the primary cannot go back to service, and there will definitely be an election for the new primary, is there a way to tell mongo to automatically search and connect to the new primary of the replica set?
Possibly your problem is that you're only connecting to one node, the one which is primary at that time. What you need to to do is to specify, when connecting, what the replicaset is and what the address is of each available node - so your client can reconnect to a different node if its primary falls over.
The documentation on the Mongo URI connection string format explains this:
hostX : Optional. You can specify as many hosts as necessary. You would specify multiple hosts, for example, for connections to replica sets.
It gives this example:
EXAMPLE
To describe a connection to a replica set named test, with the following mongod hosts:
db1.example.net on port 27017 and
db2.example.net on port 2500.
You would use a connection string that resembles the following:
mongodb://db1.example.net,db2.example.net:2500/?replicaSet=test
You may need to check your driver's documentation also, in case it requires a particular way of specifying the replica set and the list of nodes.
This was not the problem. The replica set was well defined and configured. The problem was really weird, I'm guessing it is a bug in the terminal. All I did was I closed the terminal, opened a new one, and it was working like a charm

How to specify the replicaSet name with ReactiveMongo?

When opening a connection to multiple mongoDB servers with ReactiveMongo, we can pass it a list of hosts to connect to.
However I don't find any way to provide the replicaSet name (as we can do in standard MongoDB URIs). Even the URI parser of ReactiveMongo ignores it.
Is it a problem? Will the driver it work correctly without knowledge of the replicaSet name?
The list you provide is called "seed list". When your driver connects to one of these servers, be it a primary or secondary, the driver will be informed that it connected to the replica set and which server is the current primary (if there is one) amongst other details.
Your driver even should be informed when a new primary elected and it should automatically connect to the newly elected primary.
As per ReactiveMongo docs which you should read throughly:
[...]ReactiveMongo provides support for Replica Sets. That means the following:
the driver will detect if it is connected to a Replica Set;
it will probe for the other nodes in the set and connect to them;
it will detect when the primary has changed and guess which is the new one;
[...]

How to add new server in replica set in production

I am new to mongodb replica set.
According to Replic Set Ref this should be connection string in my application to connect to mongodb
mongodb://db1.example.net,db2.example.net,db3.example.net:2500/?replicaSet=test
Suppose this is production replica set (i.e. I cannot change application code or stop all the mongo servers) And, I want to add another mongo db instance db4.example.net in test replica set. How will I do that?
How my application will know about the new db4.example.net
If you are looking for real-world scenario:
In situation when any of existing server is down due to hardware failure etc, it is natural to add another db server to the replica set to preserve the redundancy. But, how to do that.
The list of replica set hosts in your connection string is a "seed list", and does not have to include all of the members of your replica set.
The MongoDB client driver used by your application will iterate through the seed list until it can successfully connect to a host, and use that host to request the current replica set configuration which will list all current members of the replica set. Per the documentation, it is recommended to include at least two hosts in the connect string so that your driver can still connect in the event the first host happens to be down.
Any changes in replica set configuration (i.e. adding/removing members or election of a new primary) are automatically discovered by your client driver so you should not have to make any changes in the application configuration to add a new member to your replica set.
A change in replica set configuration may trigger an election for a new primary, so your application code should expect to handle transient errors for a few seconds during reconfiguration.
Some helpful mongo shell commands:
rs.conf() - display the current replication configuration
db.isMaster().primary - display the current primary
You should notice a version number in the configuration document returned by rs.conf(). This version is incremented on every configuration change so drivers and replica set nodes can check if they have a stale version of the config.
How my application will know about the new db4.example.net
Just rs.add("db4.example.net") and your application should discover this host automatically.
In your scenario, if you are replacing an entirely dead host you would likely also want to rs.remove() the original host (after adding the replacement) to maintain the voting majority for your replica set.
Alternatively, rather than adding a host with a new name you could replace the dead host with a new server using the same hostname as previously configured. For example, if db3.example.net died, you could replace it with a new db3.example.net and follow the steps to Resync a replica set member.
A way to provide abstraction to your database is to set up a sharded cluster. In that case, the access point between your application and the database are the mongodb routers. What happens behind them is outside of the visibility of the application. You can add shards, remove shards, turn shards into replica-sets and change those replica-sets all you want. The application keeps talking with the routers, and the routers know which servers they need to forward them. You can change the cluster configuration at runtime by connecting to the routers with the mongo shell.
When you have questions about how to set up and administrate MongoDB clusters, please ask on http://dba.stackexchange.com.
But note that in the scenario you described, that wouldn't even be necessary. When one of your database servers has a hardware failure and your system administrators want to replace it without application downtime, they can just assign the same IP and hostname to the new server so the application doesn't even notice that it's a replacement.
When you want to know details about how to do this, you will find help on http://serverfault.com