2

I have a pretty simple PyMongo configuration that connects to two hosts:

from pymongo import MongoClient

host = os.getenv('MONGODB_HOST', '127.0.0.1')
port = int(os.getenv('MONGODB_PORT', 27017))
hosts = []
for h in host.split(','):
    hosts.append('{}:{}'.format(h, port))
cls.client = MongoClient(host=hosts, replicaset='replicatOne')

MONGODB_HOST is composed of a list of two ips, such as "primary_mongo,secondary_mongo"

They are configured as a replica set.

The issue I notice is that, in this current configuration, if secondary_mongo goes down, my whole code stops working.

I believe that giving a list of hosts to MongoClient would tell it "use the one that works, starting with the first", but it appears it's not correct.

What is wrong and how can I ensure that MongoClient connects properly to primary_mongo first, and in the event it fails, goes to secondary_mongo ?

halfer
  • 19,824
  • 17
  • 99
  • 186
Cyril N.
  • 38,875
  • 36
  • 142
  • 243
  • Do you have only two nodes, i.e. one primary and one secondary? – Wernfried Domscheit Oct 21 '21 at 09:01
  • Yes, the secondary is a backup in case the primary goes down, that's all. But since it never happened, I don't really see the need for a third. Why? – Cyril N. Oct 21 '21 at 09:06
  • A two member replica set does not provide any high availability, see [Three Member Replica Sets](https://docs.mongodb.com/manual/core/replica-set-architecture-three-members/) Consider a Primary-Secondary-Arbiter setup. – Wernfried Domscheit Oct 21 '21 at 09:18
  • Maybe, but is this related to the question ? ;) – Cyril N. Oct 21 '21 at 14:34
  • ? Seriously ? So right now I have a redundant server that is completely useless? ... Is there a way to automatically make it work without having to set up a third server? (you mention `secondaryOk`, can this be automated? – Cyril N. Oct 21 '21 at 15:14
  • The DB goes to read only mode. It depends on your application whether it will work. As far as I remember you have to connect with open `primaryPreferred` check the documentation – Wernfried Domscheit Oct 21 '21 at 15:26
  • Isn't it possible to then configure Mongo to use one of the two db that is currently working, starting with the one, then going to the second if the one fails. I'm simply hoping for that – Cyril N. Oct 21 '21 at 16:11

1 Answers1

5

In order to have a fully running MongoDB ReplicaSet you must have a PRIMARY member. A PRIMARY can be only elected if the majority of all members is available. 1 out of 2 is not the majority, thus your MongoDB ReplicaSet goes down if one node fails.

When you connect to your MongoDB then you can connect either to the ReplicaSet, e.g.

mongo "mongodb://localhost:27037,localhost:27137,localhost:27237/?replicaSet=repSet"

or you connect directly, e.g.

mongo "mongodb://localhost:27037,localhost:27137"

When you connect to a ReplicaSet and the PRIMARY goes down (or when it steps down to SECONDARY for whatever reason) and another member becomes the PRIMARY, then usually the client automatically reconnect to the new PRIMARY. However, connecting to a ReplicaSet requires a PRIMARY member, i.e. the majority of members must be available.

When you connect directly, then you can also connect to a SECONDARY member and use the MongoDB in read/only mode. However, you don't have any failover/reconnect function if the connected member goes down.

You could create an ARBITER member on one of your nodes. Then, if the other node goes down, the application is still fully available. Bear in mind, by this setup you can lose only the "second" host but not either of them. In best case you configure the ARBITER on an independent third location.

From the MongoDB: The Definitive Guide by Shannon Bradshaw, Eoin Brazil, Kristina Chodorow: Part III - Replication, CHAPTER 9 - Setting Up a Replica Set:

How to Design a Set

To plan out your set, there are certain replica set concepts that you must be familiar with. The next chapter goes into more detail about these, but the most important is that replica sets are all about majorities: you need a majority of members to elect a primary, a primary can only stay primary so long as it can reach a majority, and a write is safe when it’s been replicated to a majority. This majority is defined to be “more than half of all members in the set,” as shown in Table 9-1.

Number of members in the set Majority of the set
1 1
2 2
3 2
4 3
5 3
6 4
7 4

Note that it doesn’t matter how many members are down or unavailable, as majority is based on the set’s configuration.

For example, suppose that we have a five-member set and three members go down, as shown in Figure 9-1. There are still two members up. These two members cannot reach a majority of the set (at least three members), so they cannot elect a primary. If one of them were primary, it would step down as soon as it noticed that it could not reach a majority. After a few seconds, your set would consist of two secondaries and three unreachable members.

enter image description here

Many users find this frustrating: why can’t the two remaining members elect a primary? The problem is that it’s possible that the other three members didn’t go down, and that it was the network that went down, as shown in Figure 9-2. In this case, the three members on the left will elect a primary, since they can reach a majority of the set (three members out of five).

In the case of a network partition, we do not want both sides of the partition to elect a primary: otherwise the set would have two primaries. Then both primaries would be writing to the data and the data sets would diverge. Requiring a majority to elect or stay primary is a neat way of avoiding ending up with more than one primary.

enter image description here

It is important to configure your set in such a way that you’ll usually be able to have one primary. For example, in the five-member set described above, if members 1, 2, and 3 are in one data center and members 4 and 5 are in another, there should almost always be a majority available in the first data center (it’s more likely to have a network break between data centers than within them).

Wernfried Domscheit
  • 54,457
  • 9
  • 76
  • 110
  • That's a really complete and very interesting response! Thank you very much for that! – Cyril N. Oct 22 '21 at 07:28
  • @Wernfried-Domscheit: *an arbiter is typically useful when you have an even number of replica set members. In best case, the arbiter is configured at a different location in your network. Note, the arbiter does not store any data and does almost nothing. A tiny machine is sufficient for it* [see](https://stackoverflow.com/questions/71778915/mongodb-cant-stablish-primary-in-replica-set) – Miquel Apr 08 '22 at 09:53
  • Also interesting to know that votes can be changed so majorities can be manipulated :) [mongo docs](https://www.mongodb.com/docs/manual/reference/write-concern/#mongodb-writeconcern-writeconcern.-majority-): a member with no votes, does not count for the majority of the set – Miquel Apr 08 '22 at 10:01
  • @Miquel, yes correct. In Mongo version <3.2 it was even possible to have vote values greater than 1, which makes it even more complicated. – Wernfried Domscheit Apr 08 '22 at 10:55