MongoDB ist eine NoSQL-Datenbank, die JSON-ähnliche Dokumente mit dynamischen Schemata verwendet. Wenn du mit Datenbanken arbeitest, ist es immer gut, einen Notfallplan zu haben, falls einer deiner Datenbankserver ausfällt. Du kannst die Wahrscheinlichkeit, dass das passiert, verringern, indem du ein cleveres Verwaltungstool für deine WordPress-Website nutzt.

Aus diesem Grund ist es sinnvoll, viele Kopien deiner Daten zu haben. Dadurch werden auch die Lesezeiten reduziert. Gleichzeitig kann es die Skalierbarkeit und Verfügbarkeit der Datenbank verbessern. An dieser Stelle kommt die Replikation ins Spiel. Darunter versteht man die Synchronisierung von Daten zwischen mehreren Datenbanken.

In diesem Artikel werden wir uns mit den wichtigsten Aspekten der MongoDB-Replikation befassen, z. B. mit ihren Funktionen und Mechanismen, um nur einige zu nennen.

Was ist Replikation in MongoDB?

In MongoDB führen Replikatsätze die Replikation durch. Das ist eine Gruppe von Servern, die durch Replikation denselben Datensatz verwalten. Du kannst die MongoDB-Replikation sogar als Teil des Lastausgleichs nutzen. Dabei kannst du die Schreib- und Lesevorgänge auf alle Instanzen verteilen, je nach Anwendungsfall.

Was ist ein MongoDB Replikatset?

Jede MongoDB-Instanz, die zu einem bestimmten Replikat-Set gehört, ist ein Mitglied. Jedes Replikatset muss ein primäres Mitglied und mindestens ein sekundäres Mitglied haben.

Das primäre Mitglied ist der primäre Zugangspunkt für Transaktionen mit dem Replikatset. Es ist auch das einzige Mitglied, das Schreiboperationen akzeptieren kann. Die Replikation kopiert zunächst das Oplog (Operations Log) des primären Mitglieds. Anschließend werden die protokollierten Änderungen in den jeweiligen Datensätzen der Sekundärdateien wiederholt. Jedes Replikatset kann also jeweils nur ein primäres Mitglied haben. Wenn mehrere Primaries Schreiboperationen erhalten, kann es zu Datenkonflikten kommen.

Normalerweise fragen die Anwendungen nur das primäre Mitglied für Schreib- und Lesevorgänge ab. Du kannst dein Setup so gestalten, dass es von einem oder mehreren sekundären Mitgliedern liest. Die asynchrone Datenübertragung kann dazu führen, dass die Lesevorgänge der sekundären Knotenpunkte alte Daten liefern. Daher ist eine solche Anordnung nicht für jeden Anwendungsfall ideal.

Funktionen des Replikatsets

Der automatische Failover-Mechanismus unterscheidet MongoDBs Replikatsätze von denen der Konkurrenz. Fällt ein primärer Knoten aus, wird durch eine automatische Wahl unter den sekundären Knoten ein neuer primärer Knoten ausgewählt.

MongoDB Replikatset vs. MongoDB Cluster

Ein MongoDB Replikatset erstellt verschiedene Kopien desselben Datensatzes auf den Replikatset-Knoten. Das Hauptziel eines Replikat-Sets ist es:

  • Eine integrierte Backup-Lösung zu bieten
  • Die Datenverfügbarkeit zu erhöhen

Ein MongoDB-Cluster ist ein ganz anderes Spiel. Er verteilt die Daten durch einen Shard-Schlüssel auf viele Knoten. Bei diesem Prozess werden die Daten in viele Teile, sogenannte Shards, zerlegt. Anschließend wird jeder Shard auf einen anderen Knoten kopiert. Ein Cluster zielt darauf ab, große Datensätze und Operationen mit hohem Durchsatz zu unterstützen. Dies wird durch eine horizontale Skalierung der Arbeitslast erreicht.

Das ist der Unterschied zwischen einem Replikatset und einem Cluster, vereinfacht ausgedrückt:

  • Ein Cluster verteilt die Arbeitslast. Außerdem speichert er Datenfragmente (Shards) auf vielen Servern.
  • Ein Replikatset dupliziert den Datensatz vollständig.

MongoDB ermöglicht es dir, diese Funktionen zu kombinieren, indem du einen Sharded-Cluster erstellst. Hier kannst du jeden Shard auf einen zweiten Server replizieren. Dadurch bietet ein Shard eine hohe Redundanz und Datenverfügbarkeit.

Die Pflege und Einrichtung eines Replikatsets kann technisch anstrengend und zeitaufwändig sein. Und die Suche nach dem richtigen Hosting-Service? Das ist ein ganz anderes Problem. Bei so vielen Angeboten kann es leicht passieren, dass du stundenlang recherchierst, anstatt dein Unternehmen aufzubauen.

Ich möchte dir ein Tool vorstellen, das dir all das und noch viel mehr abnimmt, damit du mit deinem Service/Produkt wieder durchstarten kannst.

Kinstas Anwendungs-Hosting-Lösung, auf die über 55.000 Entwickler/innen vertrauen, kannst du in nur 3 einfachen Schritten zum Laufen bringen. Wenn das zu gut klingt, um wahr zu sein, findest du hier weitere Vorteile von Kinsta:

  • Greife auf bessere Leistung zurück mit den internen Verbindungen von Kinsta: Vergiss deine Probleme mit gemeinsam genutzten Datenbanken. Wechsle zu dedizierten Datenbanken mit internen Verbindungen, bei denen es keine Begrenzung der Abfrage- oder Zeilenzahl gibt. Kinsta ist schneller, sicherer und stellt dir keine Kosten für die interne Bandbreite/den Datenverkehr in Rechnung.
  • Ein auf Entwickler zugeschnittener Funktionsumfang: Skaliere deine Anwendung auf einer robusten Plattform, die Gmail, YouTube und die Google-Suche unterstützt. Du kannst sicher sein, dass du hier in den sichersten Händen bist.
  • Genieße unvergleichliche Geschwindigkeiten in einem Rechenzentrum deiner Wahl: Wähle die Region, die für dich und deine Kunden am besten geeignet ist. Mit über 25 Rechenzentren zur Auswahl sorgen die 260+ PoPs von Kinsta für maximale Geschwindigkeit und eine globale Präsenz deiner Website.

Teste die Anwendungs-Hosting-Lösung von Kinsta noch heute kostenlos!

Wie funktioniert die Replikation in MongoDB?

In MongoDB sendest du Writer-Operationen an den primären Server (Node). Der Primärserver verteilt die Operationen auf die Sekundärserver und repliziert die Daten.

Dies ist ein Flussdiagramm, das zeigt, wie die Replikation in MongoDB für 3 Knoten (1 primärer, 2 sekundäre) funktioniert
Illustration des MongoDB-Replikationsprozesses (Bildquelle: MongoDB)

Drei Arten von MongoDB-Knoten

Von den drei Arten von MongoDB-Knoten haben wir bereits zwei kennengelernt: primäre und sekundäre Knoten. Der dritte Typ von MongoDB-Knoten, der bei der Replikation nützlich ist, ist ein Arbiter. Der Arbiter-Knoten verfügt nicht über eine Kopie des Datensatzes und kann nicht zum primären Knoten werden. Allerdings nimmt der Arbiter an den Wahlen für den Primärknoten teil.

Wir haben bereits erwähnt, was passiert, wenn der primäre Knoten ausfällt, aber was ist, wenn die sekundären Knoten ins Gras beißen? In diesem Fall wird der primäre Knotenpunkt zum sekundären und die Datenbank wird unerreichbar.

Mitgliedswahl

Die Wahlen können in den folgenden Szenarien stattfinden:

  • Initialisierung einer Replikatgruppe
  • Verlust der Verbindung zum primären Knoten (dies kann durch Heartbeats festgestellt werden)
  • Wartung eines Replikat-Sets mit den Methoden rs.reconfig oder stepDown
  • Hinzufügen eines neuen Knotens zu einem bestehenden Replikatset

Ein Replikatset kann bis zu 50 Mitglieder haben, aber nur 7 oder weniger können an einer Wahl teilnehmen.

Die durchschnittliche Zeit, bevor ein Cluster einen neuen Primar wählt, sollte 12 Sekunden nicht überschreiten. Der Wahlalgorithmus wird versuchen, den Sekundärteilnehmer mit der höchsten Priorität zu wählen. Gleichzeitig können die Mitglieder mit einem Prioritätswert von 0 nicht Primar werden und nehmen nicht an der Wahl teil.

Dieses Diagramm zeigt, wie ein sekundärer Knoten nach der Wahl zu einem primären Knoten in MongoDB wird.
Sekundärer Knotenpunkt wird zum primären (Bildquelle: Medium)

Der Write Concern

Um die Dauerhaftigkeit zu gewährleisten, haben Schreiboperationen einen Rahmen, um die Daten in eine bestimmte Anzahl von Knoten zu kopieren. Damit kannst du dem Kunden sogar eine Rückmeldung geben. Dieser Rahmen wird auch als „Write Concern“ bezeichnet Es hat datentragende Mitglieder, die ein Schreibanliegen bestätigen müssen, bevor die Operation als erfolgreich zurückgegeben wird. In der Regel haben die Replica-Sets den Wert 1 als „Write Concern“. Daher sollte nur das primäre Mitglied den Schreibvorgang bestätigen, bevor es die Bestätigung des Schreibvorgangs zurückgibt.

Du kannst sogar die Anzahl der Mitglieder erhöhen, die für die Bestätigung des Schreibvorgangs erforderlich sind. Es gibt keine Obergrenze für die Anzahl der Mitglieder. Wenn die Anzahl jedoch hoch ist, musst du mit einer hohen Latenz rechnen. Das liegt daran, dass der Client auf die Bestätigung aller Mitglieder warten muss. Du kannst auch die „Mehrheit“ festlegen, d.h. mehr als die Hälfte der Mitglieder stimmen zu, nachdem sie ihre Bestätigung erhalten haben.

Lesepräferenz

Für die Lesevorgänge kannst du die Lesepräferenz angeben, welche beschreibt, wie die Datenbank die Abfrage an die Mitglieder des Replikatsets weiterleitet. In der Regel erhält der primäre Knoten den Lesevorgang, aber der Kunde kann eine Lesepräferenz angeben, um die Lesevorgänge an sekundäre Knoten zu senden. Hier sind die Optionen für die Lesepräferenz:

  • primaryPreferred: Normalerweise kommen die Lesevorgänge vom primären Knotenpunkt, aber wenn dieser nicht verfügbar ist, werden die Daten von den sekundären Knotenpunkten abgerufen.
  • primary: Alle Lesevorgänge werden vom primären Knoten ausgeführt.
  • secondary: Alle Lesevorgänge werden von den sekundären Knotenpunkten ausgeführt.
  • nearest: Hier werden die Leseanfragen an den nächstgelegenen erreichbaren Knoten weitergeleitet, der mit dem Befehl ping ermittelt werden kann. Das Ergebnis der Lesevorgänge kann von jedem Mitglied des Replikatsets stammen, unabhängig davon, ob es sich um den primären oder den sekundären Knoten handelt.
  • secondaryPreferred: Hier kommen die meisten Lesevorgänge von den sekundären Knoten, aber wenn keiner von ihnen verfügbar ist, werden die Daten vom primären Knoten übernommen.

Replikationsset Datensynchronisation

Um die Kopien des gemeinsamen Datensatzes auf dem neuesten Stand zu halten, replizieren oder synchronisieren die sekundären Mitglieder eines Replikationssets die Daten der anderen Mitglieder.

MongoDB nutzt zwei Formen der Datensynchronisierung. Erstsynchronisierung, um neue Mitglieder mit dem vollständigen Datensatz zu versorgen. Replikation, um laufende Änderungen am kompletten Datensatz durchzuführen.

Erstsynchronisation

Bei der Erstsynchronisierung führt ein sekundärer Knoten den Befehl init sync aus, um alle Daten vom primären Knoten mit einem anderen sekundären Knoten zu synchronisieren, der die neuesten Daten enthält. Daher nutzt der sekundäre Knoten konsequent die Funktion tailable cursor , um die neuesten Oplog-Einträge in der local.oplog.rs-Sammlung des primären Knotens abzufragen und diese Vorgänge innerhalb dieser Oplog-Einträge durchzuführen.

Ab MongoDB 5.2 können die ersten Synchronisierungen auf Dateikopien basieren oder logisch sein.

Logische Synchronisierung

Wenn du eine logische Synchronisierung durchführst, tut MongoDB folgendes:

  1. Entwickelt alle Sammelindizes, während die Dokumente für jede Sammlung kopiert werden.
  2. Dupliziert alle Datenbanken außer der lokalen Datenbank. mongod scannt jede Sammlung in allen Quelldatenbanken und fügt alle Daten in die Duplikate dieser Sammlungen ein.
  3. Führt alle Änderungen an der Datenmenge aus. Durch die Nutzung des Oplogs der Quelle aktualisiert mongod seinen Datensatz, um den aktuellen Zustand des Replikatsatzes abzubilden.
  4. Extrahiert während der Datenkopie neu hinzugefügte oplog-Datensätze. Vergewissere dich, dass das Zielmitglied über genügend Speicherplatz in der lokalen Datenbank verfügt, um diese Oplog-Datensätze für die Dauer dieser Datenkopiephase vorläufig zu speichern.

Wenn die Erstsynchronisation abgeschlossen ist, wechselt das Mitglied von STARTUP2 zu SECONDARY .

Dateikopie-basierte Erstsynchronisation

Diesen Vorgang kannst du nur ausführen, wenn du MongoDB Enterprise verwendest. Bei diesem Prozess wird die erste Synchronisierung durch Duplizieren und Verschieben der Dateien im Dateisystem durchgeführt. Diese Synchronisierungsmethode kann in manchen Fällen schneller sein als die logische Erstsynchronisierung. Bedenke, dass die erste Synchronisierung durch Dateikopien zu ungenauen Zählungen führen kann, wenn du die count()-Methode ohne ein Abfrageprädikat ausführst.

Aber auch diese Methode hat ihre Tücken:

  • Während eines ersten Abgleichs mit einer Dateikopie kannst du nicht in die lokale Datenbank des Mitglieds schreiben, das abgeglichen wird. Du kannst auch keine Sicherungskopie des Mitglieds, mit dem synchronisiert wird, oder des Mitglieds, von dem synchronisiert wird, erstellen.
  • Wenn du die verschlüsselte Speicher-Engine nutzt, verwendet MongoDB den Quellschlüssel, um das Ziel zu verschlüsseln.
  • Du kannst jeweils nur eine erste Synchronisierung von einem bestimmten Mitglied aus durchführen.

Replikation

Sekundäre Mitglieder replizieren die Daten nach der ersten Synchronisierung konsistent. Sekundäre Mitglieder duplizieren das Oplog aus ihrer Synchronisierung mit der Quelle und führen diese Vorgänge in einem asynchronen Prozess aus.

Die sekundären Mitglieder sind in der Lage, ihre Synchronisierung mit der Quelle bei Bedarf automatisch zu ändern, wenn sich die Ping-Zeit und der Status der Replikation der anderen Mitglieder ändern.

Streaming-Replikation

Ab MongoDB 4.4 sendet die Synchronisierung von Quellen einen kontinuierlichen Strom von Oplog-Einträgen an ihre synchronisierenden Secondaries. Die Streaming-Replikation verringert die Verzögerung der Replikation in Netzwerken mit hoher Last und hoher Latenz. Sie kann auch:

  • Das Risiko verringern, dass Schreibvorgänge mit w:1 aufgrund eines primären Failovers verloren gehen.
  • Die Staleness bei Lesevorgängen von Secondaries verringern.
  • Die Latenz bei Schreibvorgängen mit w:“majority” und w:>1 verringern. Kurz gesagt: alle Schreibvorgänge, die auf die Replikation warten müssen.
Multithreaded Replikation

In MongoDB werden Schreibvorgänge in Batches über mehrere Threads ausgeführt, um die Gleichzeitigkeit zu verbessern. MongoDB gruppiert die Batches nach Dokument-ID und führt jede Gruppe von Operationen in einem anderen Thread aus.

MongoDB führt die Schreibvorgänge für ein bestimmtes Dokument immer in der ursprünglichen Reihenfolge aus. Das hat sich in MongoDB 4.0 geändert.

Ab MongoDB 4.0 werden Leseoperationen, die auf Secondaries abzielen und mit einem Read Concern Level von “majority” oder “local” konfiguriert sind, nun von einem WiredTiger-Snapshot der Daten gelesen, wenn der Lesevorgang auf einer Secondary stattfindet, auf der die Replikationsbatches angewendet werden. Das Lesen aus einem Snapshot garantiert eine konsistente Sicht auf die Daten und ermöglicht es, dass das Lesen gleichzeitig mit der laufenden Replikation erfolgt, ohne dass eine Sperre erforderlich ist.

Daher müssen sekundäre Lesevorgänge, die diese Read Concern Level benötigen, nicht mehr auf die Anwendung von Replikationsbatches warten, sondern können sofort nach ihrem Eingang bearbeitet werden.

Wie man ein MongoDB Replikatset erstellt

Wie bereits erwähnt, verwaltet MongoDB die Replikation über Replikatsätze. In den nächsten Abschnitten stellen wir dir einige Methoden vor, mit denen du Replikatgruppen für deinen Anwendungsfall erstellen kannst.

Methode 1: Erstellen eines neuen MongoDB-Replikatsets unter Ubuntu

Bevor wir loslegen, musst du sicherstellen, dass du mindestens drei Server mit Ubuntu 20.04 hast, auf denen MongoDB installiert ist.

Um ein Replikatset einzurichten, musst du eine Adresse angeben, unter der jedes Mitglied des Replikatsets von den anderen Mitgliedern des Sets erreicht werden kann. In diesem Fall haben wir drei Mitglieder im Set. Wir können zwar IP-Adressen verwenden, aber das ist nicht empfehlenswert, da sich die Adressen unerwartet ändern können. Eine bessere Alternative ist die Verwendung der logischen DNS-Hostnamen bei der Konfiguration von Replikatgruppen.

Dazu konfigurieren wir die Subdomain für jedes Replikationsmitglied. Obwohl dies für eine Produktionsumgebung ideal sein kann, wird in diesem Abschnitt beschrieben, wie die DNS-Auflösung konfiguriert wird, indem die jeweiligen Hosts-Dateien der einzelnen Server bearbeitet werden. Diese Datei ermöglicht es uns, numerischen IP-Adressen lesbare Hostnamen zuzuweisen. Wenn sich also deine IP-Adresse ändert, brauchst du nur die Hosts-Dateien auf den drei Servern zu aktualisieren, anstatt das Replikatset von Grund auf neu zu konfigurieren!

Meistens wird hosts im Verzeichnis /etc/ gespeichert. Wiederhole die folgenden Befehle für jeden deiner drei Server:

sudo nano /etc/hosts

Im obigen Befehl verwenden wir nano als Texteditor, du kannst aber auch einen anderen Texteditor verwenden, den du bevorzugst. Nach den ersten Zeilen, die den localhost konfigurieren, fügst du einen Eintrag für jedes Mitglied des Replikatorsets hinzu. Diese Einträge haben die Form einer IP-Adresse, gefolgt von einem lesbaren Namen deiner Wahl. Du kannst sie benennen, wie du willst, aber achte darauf, dass sie beschreibend sind, damit du zwischen den einzelnen Mitgliedern unterscheiden kannst. Für dieses Tutorial verwenden wir die folgenden Hostnamen:

  • mongo0.replset.member
  • mongo1.replset.member
  • mongo2.replset.member

Mit diesen Hostnamen würden deine /etc/hosts-Dateien ähnlich wie die folgenden markierten Zeilen aussehen:

Dies ist ein Schnappschuss der /etc/hosts-Dateien, die die Hostnamen zusammen mit der IP-Adresse enthalten.
Hostnamen Abbildung

Speichere und schließe die Datei.

Nachdem wir die DNS-Auflösung für das Replikatorset konfiguriert haben, müssen wir die Firewall-Regeln aktualisieren, damit sie miteinander kommunizieren können. Führe den folgenden ufw Befehl auf mongo0 aus, um mongo1 den Zugriff auf Port 27017 auf mongo0 zu ermöglichen:

sudo ufw allow from mongo1_server_ip to any port 27017

Anstelle des Parameters mongo1_server_ip gibst du die tatsächliche IP-Adresse deines mongo1-Servers ein. Wenn du die Mongo-Instanz auf diesem Server aktualisiert hast, um einen anderen Port als den Standardport zu verwenden, musst du auch den Port 27017 ändern, damit er dem Port entspricht, den deine MongoDB-Instanz verwendet.

Füge nun eine weitere Firewall-Regel hinzu, um mongo2 Zugriff auf denselben Port zu geben:

sudo ufw allow from mongo2_server_ip to any port 27017

Anstelle des Parameters mongo2_server_ip gibst du die tatsächliche IP-Adresse deines mongo2-Servers ein. Aktualisiere dann die Firewall-Regeln für deine beiden anderen Server. Führe die folgenden Befehle auf dem mongo1-Server aus und achte darauf, dass du die IP-Adressen anstelle des server_ip-Parameters so änderst, dass sie denen von mongo0 bzw. mongo2 entsprechen:

sudo ufw allow from mongo0_server_ip to any port 27017
sudo ufw allow from mongo2_server_ip to any port 27017

Zuletzt führst du diese beiden Befehle auf mongo2 aus. Achte auch hier darauf, dass du die richtigen IP-Adressen für jeden Server eingibst:

sudo ufw allow from mongo0_server_ip to any port 27017
sudo ufw allow from mongo1_server_ip to any port 27017

Im nächsten Schritt musst du die Konfigurationsdatei jeder MongoDB-Instanz aktualisieren, um externe Verbindungen zuzulassen. Um dies zu ermöglichen, musst du die Konfigurationsdatei jedes Servers ändern, um die IP-Adresse und das Replikatset anzugeben. Du kannst jeden beliebigen Texteditor verwenden, aber wir benutzen wieder den Texteditor nano. Wir nehmen die folgenden Änderungen in jeder mongod.conf-Datei vor.

Auf mongo0:

# network interfaces
net:
port: 27017
bindIp: 127.0.0.1,mongo0.replset.member# replica set
replication:
replSetName: "rs0"

Auf mongo1:

# network interfaces
net:
port: 27017
bindIp: 127.0.0.1,mongo1.replset.member
replication:
replSetName: "rs0"

Auf mongo2:

# network interfaces
net:
port: 27017
bindIp: 127.0.0.1,mongo2.replset.member
replication:
replSetName: "rs0"
sudo systemctl restart mongod

Damit hast du die Replikation für die MongoDB-Instanz jedes Servers aktiviert.

Jetzt kannst du das Replikat-Set mit der Methode rs.initiate() initialisieren. Diese Methode muss nur auf einer einzigen MongoDB-Instanz im Replikatset ausgeführt werden. Vergewissere dich, dass der Name und das Mitglied des Replikatsets mit den Konfigurationen übereinstimmen, die du zuvor in den einzelnen Konfigurationsdateien vorgenommen hast.

rs.initiate(
  {
    _id: "rs0",
    members: [
      { _id: 0, host: "mongo0.replset.member" },
      { _id: 1, host: "mongo1.replset.member" },
      { _id: 2, host: "mongo2.replset.member" }
    ]
  }
)

Wenn die Methode „ok“: 1 als Output zurückgibt, bedeutet das, dass das Replikatset korrekt gestartet wurde. Unten siehst du ein Beispiel dafür, wie die Ausgabe aussehen sollte:

 "ok": 1,
  "$clusterTime": {
    "clusterTime": Timestamp(1612389071, 1),
    "signature": {
      "hash": BinData(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
      "keyId": NumberLong(0)
    }
  },
  "operationTime": Timestamp(1612389071, 1)
}

MongoDB-Server herunterfahren

Du kannst einen MongoDB-Server mit der Methode db.shutdownServer() herunterfahren. Nachfolgend findest du die Syntax für diese Methode. Sowohl force als auch timeoutsecs sind optionale Parameter.

db.shutdownServer({
force: <boolean>,
timeoutSecs: <int>
})

Diese Methode kann fehlschlagen, wenn das MongoDB-Mitglied bestimmte Operationen wie den Indexaufbau durchführt. Um die Operationen zu unterbrechen und das Mitglied zum Herunterfahren zu zwingen, kannst du den booleschen Parameter force auf true setzen.

MongoDB mit –replSet neu starten

Um die Konfiguration zurückzusetzen, stellst du sicher, dass alle Knoten in deinem Replikatset angehalten sind. Lösche dann die lokale Datenbank für jeden Knoten. Starte sie erneut mit dem Flag –replSet und führe rs.initiate() nur auf einer MongoDB-Instanz für das Replikatset aus.

mongod --replSet "rs0"

rs.initiate() kann ein optionales Replikatset-Konfigurationsdokument nehmen, nämlich:

  • Die Replication.replSetName oder die —replSet Option, um den Namen des Replikatsets im Feld _id anzugeben.
  • Das Array „members“, das ein Dokument für jedes Mitglied des Replikatorsatzes enthält.

Die Methode rs.initiate() löst eine Wahl aus und wählt eines der Mitglieder zum Primärmitglied.

Mitglieder zum Replikatset hinzufügen

Um Mitglieder zum Set hinzuzufügen, startest du Mongo-Instanzen auf verschiedenen Rechnern. Starte dann einen Mongo-Client und verwende den Befehl rs.add().

Der Befehl rs.add() hat die folgende grundlegende Syntax:

rs.add(HOST_NAME:PORT)

Zum Beispiel,

Angenommen, mongo1 ist deine Mongo-Instanz, die auf Port 27017 zu hört. Verwende den Mongo-Client-Befehl rs.add(), um diese Instanz zum Replikatset hinzuzufügen.

rs.add("mongo1:27017")

Erst wenn du mit dem primären Knoten verbunden bist, kannst du eine Mongo-Instanz zum Replikatset hinzufügen. Um zu überprüfen, ob du mit dem primären Knoten verbunden bist, verwende den Befehl db.isMaster().

Mitglieder entfernen

Um ein Mitglied zu entfernen, können wir rs.remove()nutzen.

Dazu musst du zunächst die Mongod-Instanz, die du entfernen möchtest, mit der oben beschriebenen Methode db.shutdownServer() herunterfahren.

Als Nächstes verbindest du dich mit der aktuellen Primärinstanz des Replikationssets. Um die aktuelle Primärinstanz zu ermitteln, benutze db.hello(), während du mit einem beliebigen Mitglied des Replikatorsets verbunden bist. Sobald du die Primärinstanz ermittelt hast, führst du einen der folgenden Befehle aus:

rs.remove("mongodb-node-04:27017")
rs.remove("mongodb-node-04")
Dies ist ein Schnappschuss der Ausgabe nach der Ausführung des Befehls rs.remove().
Das obige Bild zeigt, dass der Knoten erfolgreich aus dem Replikatset entfernt wurde (Bildquelle: Bmc)

Wenn das Replikat-Set einen neuen Primärknoten wählen muss, kann es sein, dass MongoDB die Verbindung kurzzeitig unterbricht. In diesem Fall wird die Verbindung automatisch wiederhergestellt. Außerdem kann die Fehlermeldung DBClientCursor::init call() angezeigt werden, obwohl der Befehl erfolgreich war.

Methode 2: Konfigurieren eines MongoDB-Replikat-Sets für die Bereitstellung und den Test

Generell kannst du Replikatsätze für Tests entweder mit aktiviertem oder deaktiviertem RBAC einrichten. In dieser Methode werden wir Replikatsätze mit deaktivierter Zugriffskontrolle einrichten, um sie in einer Testumgebung einzusetzen.

Erstelle zunächst mit dem folgenden Befehl Verzeichnisse für alle Instanzen, die Teil des Replikatsets sind:

mkdir -p /srv/mongodb/replicaset0-0  /srv/mongodb/replicaset0-1 /srv/mongodb/replicaset0-2

Dieser Befehl erstellt Verzeichnisse für die drei MongoDB-Instanzen replicaset0-0, replicaset0-1 und replicaset0-2. Starte nun die MongoDB-Instanzen für jede von ihnen mit den folgenden Befehlen:

Für Server 1:

mongod --replSet replicaset --port 27017 --bind_ip localhost,<hostname(s)|ip address(es)> --dbpath /srv/mongodb/replicaset0-0  --oplogSize 128

Für Server 2:

mongod --replSet replicaset --port 27018 --bind_ip localhost,<hostname(s)|ip address(es)> --dbpath /srv/mongodb/replicaset0-0  --oplogSize 128

Für Server 3:

mongod --replSet replicaset --port 27019 --bind_ip localhost,<hostname(s)|ip address(es)> --dbpath /srv/mongodb/replicaset0-0  --oplogSize 128

Der Parameter –oplogSize wird verwendet, um zu verhindern, dass der Rechner während der Testphase überlastet wird. Er hilft dabei, den Speicherplatz zu reduzieren, den jede Festplatte verbraucht.

Verbinde dich nun mit einer der Instanzen über die Mongo-Shell, indem du die unten angegebene Portnummer verwendest.

mongo --port 27017

Wir können den Befehl rs.initiate() verwenden, um den Replikationsprozess zu starten. Du musst den Parameter hostname durch den Namen deines Systems ersetzen.

rs conf = {

  _id: "replicaset0",

  members: [

    {  _id: 0,  host: "<hostname>:27017},

    {  _id: 1,  host: "<hostname>:27018"},

    {  _id: 2,  host: "<hostname>:27019"}

   ] }

Du kannst nun die Konfigurationsobjektdatei als Parameter für den Befehl initiate übergeben und ihn wie folgt verwenden:

rs.initiate(rsconf)

Und da hast du es! Du hast erfolgreich ein MongoDB Replikatset für Entwicklungs– und Testzwecke erstellt.

Methode 3: Umwandlung einer Standalone-Instanz in ein MongoDB-Replikatset

MongoDB ermöglicht es seinen Nutzern, ihre Standalone-Instanzen in Replikat-Sets umzuwandeln. Während eigenständige Instanzen meist für die Test- und Entwicklungsphase verwendet werden, sind Replika-Sets Teil der Produktionsumgebung.

Um loszulegen, fahren wir unsere MongoDB-Instanz mit dem folgenden Befehl herunter:

db.adminCommand({"shutdown":"1"})

Starte deine Instanz neu, indem du den Parameter –repelSet in deinem Befehl verwendest, um das Replikatset anzugeben, das du verwenden willst:

mongod --port 27017 – dbpath /var/lib/mongodb  --replSet replicaSet1 --bind_ip localhost,<hostname(s)|ip address(es)>

Du musst den Namen deines Servers zusammen mit der eindeutigen Adresse in dem Befehl angeben.

Verbinde die Shell mit deiner MongoDB-Instanz und benutze den Befehl initiate, um den Replikationsprozess zu starten und die Instanz erfolgreich in ein Replikatset umzuwandeln. Du kannst alle grundlegenden Operationen wie das Hinzufügen oder Entfernen einer Instanz mit den folgenden Befehlen durchführen:

rs.add(“<host_name:port>”)
rs.remove(“host-name”)

Außerdem kannst du den Status deines MongoDB-Replikat-Sets mit den Befehlen rs.status() und rs.conf() überprüfen.

Methode 4: MongoDB Atlas – eine einfachere Alternative

Replikation und Sharding können zusammen einen sogenannten Sharded-Cluster bilden. Auch wenn die Einrichtung und Konfiguration recht zeitaufwändig, aber einfach ist, ist MongoDB Atlas eine bessere Alternative als die zuvor genannten Methoden.

Er automatisiert deine Replikatsätze und macht den Prozess so einfach zu implementieren. Mit wenigen Klicks lassen sich globale Replikatsätze einrichten, die Disaster Recovery, einfachere Verwaltung, Datenlokalität und den Einsatz in mehreren Regionen ermöglichen.

In MongoDB Atlas müssen wir Cluster erstellen, die entweder ein Replikatset oder ein Sharded-Cluster sein können. Für ein bestimmtes Projekt ist die Anzahl der Knoten in einem Cluster in anderen Regionen auf insgesamt 40 begrenzt.

Davon ausgenommen sind die freien oder gemeinsam genutzten Cluster und die Google Cloud Regionen, die miteinander kommunizieren. Die Gesamtzahl der Knoten zwischen zwei beliebigen Regionen muss dieser Beschränkung entsprechen. Zum Beispiel, wenn es ein Projekt gibt, in dem:

  • Region A 15 Knoten hat.
  • Region B 25 Knoten hat
  • Region C 10 Knoten hat

Wir können der Region C nur 5 weitere Knoten zuweisen, da,

  1. Region A + Region B = 40; erfüllt die Bedingung, dass 40 die maximal zulässige Anzahl von Knoten ist.
  2. Region B + Region C = 25+10+5 (zusätzliche Knoten, die C zugewiesen werden) = 40; erfüllt die Bedingung, dass 40 die maximal zulässige Anzahl von Knoten ist.
  3. Region A + Region C =15+10+5 (zusätzliche Knoten, die C zugewiesen werden) = 30; erfüllt die Bedingung, dass 40 die maximal zulässige Anzahl von Knoten ist.

Wenn wir der Region C 10 weitere Knoten zuweisen, so dass die Region C 20 Knoten hat, dann sind Region B + Region C = 45 Knoten. Dies würde die vorgegebene Beschränkung überschreiten, so dass du möglicherweise keinen Multi-Regionen-Cluster erstellen kannst.

Wenn du einen Cluster erstellst, legt Atlas im Projekt einen Netzwerkcontainer für den Cloud-Anbieter an, falls dieser vorher nicht vorhanden war. Um einen Replikatsatz-Cluster in MongoDB Atlas zu erstellen, führst du den folgenden Befehl im Atlas CLI aus:

atlas clusters create [name] [options]

Achte darauf, dass du einen aussagekräftigen Clusternamen angibst, da er nach der Erstellung des Clusters nicht mehr geändert werden kann. Das Argument kann ASCII-Buchstaben, Zahlen und Bindestriche enthalten.

Für die Erstellung von Clustern in MongoDB gibt es je nach deinen Anforderungen verschiedene Optionen. Wenn du zum Beispiel ein kontinuierliches Cloud-Backup für deinen Cluster möchtest, setze --backup auf true.

Umgang mit der Replikationsverzögerung

Die Replikationsverzögerung kann ziemlich unangenehm sein. Dabei handelt es sich um eine Verzögerung zwischen einem Vorgang auf dem primären und der Anwendung dieses Vorgangs auf dem sekundären Server. Wenn dein Unternehmen mit großen Datensätzen arbeitet, ist eine Verzögerung bis zu einem gewissen Grad zu erwarten. Manchmal können aber auch externe Faktoren dazu beitragen und die Verzögerung ansteigen lassen. Um von einer aktuellen Replikation zu profitieren, stelle sicher, dass:

  1. Du deinen Netzwerkverkehr mit einer stabilen und ausreichenden Bandbreite leitest. Wenn das Netzwerk nicht ausreicht, um die Anforderungen des Replikationsprozesses zu erfüllen, kommt es zu Verzögerungen bei der Replikation der Daten im gesamten Replikatset.
  2. Du einen ausreichenden Festplattendurchsatz hast. Wenn das Dateisystem und das Festplattengerät auf dem sekundären Knoten nicht in der Lage sind, die Daten so schnell auf die Festplatte zu übertragen wie der primäre Knoten, kann der sekundäre Knoten nicht mithalten. Daher verarbeiten die sekundären Knoten die Schreibanfragen langsamer als der primäre Knoten. Dies ist ein häufiges Problem in den meisten mandantenfähigen Systemen, einschließlich virtualisierter Instanzen und groß angelegter Implementierungen.
  3. Du eine Schreibbestätigung nach einem bestimmten Intervall anforderst, um den Sekundärknoten die Möglichkeit zu geben, mit dem Primärknoten gleichzuziehen, insbesondere wenn du einen Massenladevorgang oder eine Dateneingabe durchführen willst, die eine große Anzahl von Schreibvorgängen auf dem Primärknoten erfordert. Die Secondaries sind nicht in der Lage, das Oplog schnell genug zu lesen, um mit den Änderungen Schritt zu halten, insbesondere bei unbestätigten Schreibanfragen.
  4. Du die laufenden Hintergrundaufgaben identifizierst. Bestimmte Aufgaben wie Cron-Jobs, Server-Updates und Sicherheitsprüfungen können unerwartete Auswirkungen auf das Netzwerk oder die Festplattennutzung haben und so zu Verzögerungen im Replikationsprozess führen.

Wenn du dir nicht sicher bist, ob es in deiner Anwendung eine Replikationsverzögerung gibt, keine Sorge – im nächsten Abschnitt geht es um Strategien zur Fehlerbehebung!

Fehlerbehebung bei MongoDB-Replikationssets

Du hast deine Replikationssets erfolgreich eingerichtet, aber du stellst fest, dass deine Daten auf den Servern inkonsistent sind. Das ist für große Unternehmen sehr beunruhigend, aber mit raschen Methoden zur Fehlerbehebung kannst du die Ursache finden und das Problem dann beheben! Im Folgenden findest du einige gängige Strategien zur Fehlerbehebung bei der Bereitstellung von Replikatsätzen, die sich als nützlich erweisen können:

Replikat-Status prüfen

Wir können den aktuellen Status des Replikat-Sets und den Status der einzelnen Mitglieder überprüfen, indem wir den folgenden Befehl in einer Mongosh-Sitzung ausführen, die mit dem primären Replikat-Set verbunden ist.

 rs.status()

Prüfen des Replikations-Lags

Wie bereits erwähnt, kann die Replikationsverzögerung ein ernsthaftes Problem darstellen, da sie dazu führt, dass „verzögerte“ Mitglieder nicht schnell zu primären werden können und die Möglichkeit besteht, dass verteilte Lesevorgänge inkonsistent sind. Wir können die aktuelle Länge des Replikationsprotokolls mit dem folgenden Befehl überprüfen:

rs.printSecondaryReplicationInfo()

Dieser Befehl gibt den Wert syncedTo zurück, d.h. den Zeitpunkt, an dem der letzte Oplog-Eintrag für jedes Mitglied in die Sekundärdatei geschrieben wurde. Hier ist ein Beispiel, um das Gleiche zu demonstrieren:

source: m1.example.net:27017
    syncedTo: Mon Oct 10 2022 10:19:35 GMT-0400 (EDT)
    0 secs (0 hrs) behind the primary
source: m2.example.net:27017
    syncedTo: Mon Oct 10 2022 10:19:35 GMT-0400 (EDT)
    0 secs (0 hrs) behind the primary

Ein verzögertes Mitglied kann als 0 Sekunden hinter dem primären Mitglied angezeigt werden, wenn die Inaktivitätszeit auf dem primären Mitglied größer ist als der Wert members[n].secondaryDelaySecs.

Verbindungen zwischen allen Mitgliedern testen

Jedes Mitglied eines Replikat-Sets muss sich mit jedem anderen Mitglied verbinden können. Stelle sicher, dass du die Verbindungen in beide Richtungen überprüfst. Meistens verhindern Firewall-Konfigurationen oder Netzwerktopologien die normale und erforderliche Konnektivität, was die Replikation blockieren kann.

Nehmen wir zum Beispiel an, dass sich die Mongod-Instanz sowohl mit localhost als auch mit dem Hostnamen „ExampleHostname“ verbindet, der mit der IP-Adresse 198.41.110.1 verbunden ist:

mongod --bind_ip localhost, ExampleHostname

Um sich mit dieser Instanz zu verbinden, müssen Remote-Clients den Hostnamen oder die IP-Adresse angeben:

mongosh --host ExampleHostname
mongosh --host 198.41.110.1

Wenn ein Replikatset aus drei Mitgliedern, m1, m2 und m3, besteht und den Standardport 27017 verwendet, solltest du die Verbindung wie folgt testen:

Auf m1:

mongosh --host m2 --port 27017
mongosh --host m3 --port 27017

Auf m2:

mongosh --host m1 --port 27017
mongosh --host m3 --port 27017

Auf m3:

mongosh --host m1 --port 27017
mongosh --host m2 --port 27017

Wenn eine Verbindung in irgendeine Richtung fehlschlägt, musst du deine Firewall-Konfiguration überprüfen und sie neu konfigurieren, um die Verbindungen zuzulassen.

Sichere Kommunikation mit Keyfile-Authentifizierung

Standardmäßig basiert die Keyfile-Authentifizierung in MongoDB auf dem Salted Challenge Response Authentication Mechanism (SCRAM). Dazu muss MongoDB die Anmeldedaten des Benutzers lesen und validieren, die eine Kombination aus Benutzername, Passwort und Authentifizierungsdatenbank enthalten, die der jeweiligen MongoDB-Instanz bekannt ist. Dies ist genau der Mechanismus, der für die Authentifizierung von Benutzern verwendet wird, die bei der Verbindung mit der Datenbank ein Passwort angeben.

Wenn du die Authentifizierung in MongoDB aktivierst, wird automatisch die rollenbasierte Zugriffskontrolle (Role-Based Access Control, RBAC) für das Replikatset aktiviert und der Benutzer erhält eine oder mehrere Rollen, die seinen Zugriff auf die Datenbankressourcen bestimmen. Wenn RBAC aktiviert ist, bedeutet das, dass nur der authentifizierte Mongo-Benutzer mit den entsprechenden Berechtigungen auf die Ressourcen des Systems zugreifen kann.

Die Schlüsseldatei wirkt wie ein gemeinsames Passwort für jedes Mitglied des Clusters. So kann jede Mongo-Instanz im Replikatorset den Inhalt der Schlüsseldatei als gemeinsames Passwort für die Authentifizierung der anderen Mitglieder im Einsatz verwenden.

Nur die Mongod-Instanzen mit der richtigen Schlüsseldatei können dem Replikatset beitreten. Die Länge eines Schlüssels muss zwischen 6 und 1024 Zeichen liegen und darf nur Zeichen im base64-Set enthalten. Bitte beachte, dass MongoDB beim Lesen der Schlüssel die Leerzeichen entfernt.

Du kannst eine Schlüsseldatei mit Hilfe verschiedener Methoden erzeugen. In diesem Tutorial verwenden wir openssl , um eine komplexe Zeichenkette mit 1024 zufälligen Zeichen zu erzeugen, die als gemeinsames Passwort verwendet werden kann. Anschließend wird chmod verwendet, um die Dateiberechtigungen so zu ändern, dass nur der Dateibesitzer Leserechte hat. Vermeide es, die Schlüsseldatei auf Speichermedien zu speichern, die leicht von der Hardware getrennt werden können, auf der die Mongod-Instanzen installiert sind, z. B. auf einem USB-Laufwerk oder einem an das Netzwerk angeschlossenen Speichergerät. Im Folgenden findest du den Befehl zum Erstellen einer Schlüsseldatei:

openssl rand -base64 756 > <path-to-keyfile>
chmod 400 <path-to-keyfile>

Als Nächstes kopierst du die Schlüsseldatei auf jedes Mitglied des Replikationssets. Stelle sicher, dass der Benutzer, der die Mongod-Instanzen betreibt, Eigentümer der Datei ist und auf die Schlüsseldatei zugreifen kann. Nachdem du das getan hast, fährst du alle Mitglieder des Replikatorsets herunter, beginnend mit den Secondaries. Sobald alle Sekundärinstanzen offline sind, kannst du mit dem Herunterfahren der Primärinstanz fortfahren. Es ist wichtig, diese Reihenfolge einzuhalten, um mögliche Rollbacks zu verhindern. Fahre nun die Mongod-Instanz herunter, indem du den folgenden Befehl ausführst:

use admin
db.shutdownServer()

Nachdem der Befehl ausgeführt wurde, sind alle Mitglieder des Replikat-Sets offline. Starten nun jedes Mitglied des Replikatorsets mit aktivierter Zugriffskontrolle neu.

Starte für jedes Mitglied des Replikationssets die mongod-Instanz entweder mit der Einstellung security.keyFile in der Konfigurationsdatei oder mit der Kommandozeilenoption --keyFile.

Wenn du eine Konfigurationsdatei verwendest, setze

  • security.keyFile auf den Pfad der Schlüsseldatei und
  • replication.replSetName auf den Namen des Replikationssets.
security:
  keyFile: <path-to-keyfile>
replication:
  replSetName: <replicaSetName>
net:
   bindIp: localhost,<hostname(s)|ip address(es)>

Starte die Mongod-Instanz mithilfe der Konfigurationsdatei:

mongod --config <path-to-config-file>

Wenn du die Kommandozeilenoptionen verwendest, starte die mongod-Instanz mit den folgenden Optionen:

  • –keyFile setzt du auf den Pfad der Schlüsseldatei, und
  • –replSet auf den Namen des Replikatsets.
mongod --keyFile <path-to-keyfile> --replSet <replicaSetName> --bind_ip localhost,<hostname(s)|ip address(es)>

Du kannst je nach Bedarf zusätzliche Optionen für deine Konfiguration angeben. Wenn du zum Beispiel möchtest, dass sich Remote-Clients mit deinem Deployment verbinden oder deine Deployment-Mitglieder auf verschiedenen Hosts laufen, gibst du die Option –bind_ip an. Weitere Informationen findest du unter Änderungen der Kompatibilität von Localhost-Bindungen.

Als Nächstes stellst du über die localhost-Schnittstelle eine Verbindung zu einem Mitglied des Replikationssets her. Du musst mongosh auf demselben physischen Rechner ausführen wie die mongod-Instanz. Diese Schnittstelle ist nur verfügbar, wenn noch keine Benutzer für die Bereitstellung erstellt wurden, und wird nach der Erstellung des ersten Benutzers automatisch geschlossen. Anschließend starten wir das Replikatset.

Führe in mongosh die Methode rs.initiate() aus:

rs.initiate(
  {
    _id: "myReplSet",
    members: [
      { _id: 0, host: "mongo1:27017" },
      { _id: 1, host: "mongo2:27017" },
      { _id: 2, host: "mongo3:27017" }
    ]
  }
)

Wie bereits erwähnt, wählt diese Methode eines der Mitglieder zum primären Mitglied des Replikatsets. Um das primäre Mitglied zu finden, verwende rs.status(). Verbinde dich mit dem primären Mitglied, bevor du fortfährst.

Erstelle nun den Benutzer Administrator. Du kannst einen Benutzer mit der Methode db.createUser() hinzufügen. Achte darauf, dass der Benutzer mindestens die Rolle userAdminAnyDatabase in der Admin-Datenbank hat.

Im folgenden Beispiel wird der Benutzer „batman“ mit der Rolle userAdminAnyDatabase in der Admin-Datenbank angelegt:

admin = db.getSiblingDB("admin")
admin.createUser(
  {
    user: "batman",
    pwd: passwordPrompt(), // or cleartext password
    roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
  }
)

Gib das Passwort ein, das du zuvor erstellt hast, wenn du dazu aufgefordert wirst.

Als Nächstes musst du dich als Benutzer Administrator authentifizieren. Verwende dazu db.auth(), um dich zu authentifizieren. Zum Beispiel:

db.getSiblingDB(„admin“).auth(„batman“, passwordPrompt()) // oder Klartextpasswort

Alternativ kannst du eine neue Mongosh-Instanz mit dem primären Replikationsset-Mitglied verbinden, indem du die Parameter -u <username>, -p <password> und --authenticationDatabase verwendest.

mongosh -u "batman" -p  --authenticationDatabase "admin"

Auch wenn du das Passwort nicht in das -p Kommandozeilenfeld eingibst, fragt mongosh nach dem Passwort.

Zum Schluss erstellst du den Cluster-Administrator. Die Rolle clusterAdmin ermöglicht den Zugriff auf Replikationsvorgänge, wie z. B. die Konfiguration des Replikatsets.

Wir erstellen einen Cluster-Administrator-Benutzer und weisen ihm die Rolle clusterAdmin in der Admin-Datenbank zu:

db.getSiblingDB("admin").createUser(
  {
    "user": "robin",
    "pwd": passwordPrompt(),     // or cleartext password
    roles: [ { "role" : "clusterAdmin", "db" : "admin" } ]
  }
)

Gib das Passwort ein, wenn du dazu aufgefordert wirst.

Wenn du möchtest, kannst du weitere Benutzer anlegen, um Clients zuzulassen und mit dem Replikatorset zu interagieren.

Und voila! Du hast die Keyfile-Authentifizierung erfolgreich aktiviert!

Zusammenfassung

Die Replikation ist eine wichtige Voraussetzung für Datenbanken, vor allem, wenn immer mehr Unternehmen expandieren. Sie verbessert die Leistung, die Datensicherheit und die Verfügbarkeit des Systems erheblich. Apropos Leistung: Für deine WordPress-Datenbank ist es von zentraler Bedeutung, Leistungsprobleme zu überwachen und sie rechtzeitig zu beheben, z. B. mit Kinsta APM, Jetpack und Freshping, um nur einige zu nennen.

Die Replikation hilft dabei, die Daten auf mehreren Servern zu schützen und verhindert, dass deine Server unter schweren Ausfallzeiten leiden (oder noch schlimmer – deine Daten ganz verloren gehen). In diesem Artikel haben wir die Erstellung eines Replikationssets und einige Tipps zur Fehlerbehebung sowie die Bedeutung der Replikation behandelt. Nutzt du die MongoDB-Replikation in deinem Unternehmen und hat sie sich für dich als nützlich erwiesen? Lass es uns im Kommentarbereich unten wissen!

Jeremy Holcombe Kinsta

Content & Marketing Editor bei Kinsta, WordPress Web Developer und Content Writer. Außerhalb von WordPress genieße ich den Strand, Golf und Filme. Außerdem habe ich Probleme mit großen Menschen ;).