Mongodb, Replikate und Fehler: {"$ err": "nicht Master und SlaveOk = false", "Code": 13435}

174

Ich habe zum ersten Mal Mongo Replica Sets ausprobiert.

Ich verwende Ubuntu auf ec2 und habe drei Instanzen hochgefahren. Ich habe die private IP-Adresse jeder Instanz verwendet. Ich habe als primären ausgewählt und unten ist der Code.

mongo --host Private IP Address
rs.initiate()
rs.add(“Private IP Address”)
rs.addArb(“Private IP Address”)

Alles an diesem Punkt ist in Ordnung. Wenn ich zur Website http://ec2-xxx-xxx-xxx-xxx.compute-1.amazonaws.com:28017/_replSet gehe, sehe ich, dass ich einen primären, einen zweiten und einen Schiedsrichter habe.

Ok, jetzt zu einem Test.

Beim primären Erstellen einer Datenbank ist dies der Code:

use tt
db.tt.save( { a : 123 } )

Auf der Sekundärseite mache ich das dann und erhalte den folgenden Fehler:

db.tt.find()
error: { "$err" : "not master and slaveOk=false", "code" : 13435 }

Ich bin sehr neu in Mongodb und repliziere, aber ich dachte, wenn ich etwas in einem mache, geht es in den anderen. Was muss ich tun, um maschinenübergreifend zu replizieren, wenn ich einen Datensatz in einen hinzufüge?

eLRuLL
quelle
fand heraus, dass ich rs.slaveOk () verwenden muss; Das lässt mich zu einer anderen Frage. Muss ich das für jede Abfrage tun? Was ist, wenn ich mich auf dem Masterknoten befinde?

Antworten:

282

Sie müssen den "Slave OK" -Modus einstellen, um die Mongo-Shell darüber zu informieren, dass Sie Lesevorgänge von einer Sekundärseite zulassen. Dies soll Sie und Ihre Anwendungen davor schützen, versehentlich konsistente Lesevorgänge durchzuführen. Sie können dies in der Shell tun mit:

rs.slaveOk()

Danach können Sie normal von Secondaries abfragen.

Ein Hinweis zur "eventuellen Konsistenz": Unter normalen Umständen haben Sekundärdateien von Replikatsätzen innerhalb einer Sekunde oder weniger dieselben Daten wie Primärdaten. Unter sehr hoher Last kann es eine Weile dauern, bis Daten, die Sie in die Primärdaten geschrieben haben, auf die Sekundärdaten repliziert werden. Dies wird als "Replikatverzögerung" bezeichnet, und das Lesen von einer verzögerten Sekundärseite wird als "eventuell konsistenter" Lesevorgang bezeichnet, da die neu geschriebenen Daten zwar irgendwann angezeigt werden (mit Ausnahme von Netzwerkfehlern usw.), dies jedoch möglicherweise nicht der Fall ist sofort verfügbar.

Bearbeiten: Sie müssen Slaveok nur einstellen, wenn Sie von Secondaries abfragen, und nur einmal pro Sitzung.

dcrosta
quelle
3
Überprüfen Sie immer das Handbuch, bevor Sie Befehle ausführen, die Sie in Ihren DBs nicht verstehen. Der Befehl kann Konsequenzen haben, die in der Antwort nicht erklärt werden. Ändert dieser Befehl die Art und Weise, wie Lesevorgänge für alle Verbindungen zum Replikatsatz verteilt werden? Besser herausfinden. Dieser Befehl wird bereits in v2.2 docs.mongodb.com/v2.2/reference/method/rs.slaveOk angezeigt. Sie können (und sollten) immer den Teil "/ manual /" einer docs.mongodb.com-URL ersetzen auf Ihre spezifische Version, um sicherzustellen, dass Sie relevante Informationen erhalten.
Bruno Bronosky
45

Gehen Sie folgendermaßen vor, um nicht rs.slaveOk()jedes Mal zu tippen:

Erstellen Sie eine Datei mit dem Namen replStart.js, die eine Zeile enthält:rs.slaveOk()

Schließen --shell replStart.jsSie dann ein, wenn Sie die Mongo-Shell starten. Wenn Sie eine lokale Verbindung zu einer einzelnen Instanz herstellen, erspart dies natürlich keine Eingabe.

Ed Norris
quelle
26
Eine bessere Möglichkeit, beim Tippen zu sparen, besteht darin rs.slaveOk(), Ihrer ~/.mongorc.jsDatei etwas hinzuzufügen , das beim Starten der Mongo-Shell automatisch ausgeführt wird.
Stennie
2
Ich finde es nützlich, die Standardkonfiguration in ~/.mongorc.jsund benutzerdefinierte Konfigurationen in replStart.jsoder adminStart.jsoder was auch immer zu setzen.
Ed Norris
41

in mongodb2.0

Sie sollten eingeben

rs.slaveOk()

im sekundären Mongod-Knoten

andyshi
quelle
11

Dies ist nur ein Hinweis für jeden, der sich mit diesem Problem unter Verwendung des Rubin-Treibers befasst

Ich hatte das gleiche Problem bei der Verwendung des Ruby Gem.

Um SlaveOk in Ruby festzulegen, übergeben Sie es einfach als Argument, wenn Sie den Client wie folgt erstellen:

mongo_client = MongoClient.new("localhost", 27017, { slave_ok: true })

https://github.com/mongodb/mongo-ruby-driver/wiki/Tutorial#making-a-connection

mongo_client = MongoClient.new # (optional host/port args)

Beachten Sie, dass 'args' das dritte optionale Argument ist.

Campeterson
quelle
1

Ich füge diese Antwort nur für eine unangenehme Situation des DB-Anbieters hinzu.

Was in unserem Fall passiert ist, ist die umgekehrte Verschiebung der primären und sekundären Datenbank (primär zu sekundär und umgekehrt) und wir erhalten den gleichen Fehler.

Überprüfen Sie daher in den Konfigurationseinstellungen den Datenbankstatus, der Ihnen möglicherweise hilft.

jit
quelle
0

Ich habe hier für den gleichen Fehler suchen, aber von Node.js nativen Treiber . Die Antwort für mich war eine Kombination von Antworten von Campeterson und Prabhat .

Das Problem ist, dass readPreferencedie Standardeinstellung auf gesetzt ist primary, was dann irgendwie zu einem verwirrenden slaveOkFehler führt. Mein Problem ist, dass ich nur von einem beliebigen Knoten aus meinem Replikatsatz lesen möchte. Ich verbinde mich nicht einmal mit ihm als Replikat. Ich verbinde mich einfach mit einem beliebigen Knoten, um daraus zu lesen.

Das Setzen readPreferenceauf primaryPreferred(oder besser auf die ReadPreference.PRIMARY_PREFERREDKonstante) hat es für mich gelöst. Geben sie nur als eine Option MongoClient.connect()oder zu client.db()oder zu einem find(), aggregate()oder eine andere Funktion.

const { MongoClient, ReadPreference } = require('mongodb');
const client = await MongoClient.connect(MONGODB_CONNECTIONSTRING, { readPreference: ReadPreference.PRIMARY_PREFERRED });
kub1x
quelle