In dieser Fallstudie betrachten wir MongoDB Sharding, „eine Datenbankarchitektur, die Daten nach Schlüsselbereichen partitioniert und auf zwei oder mehr Datenbankinstanzen verteilt. Sharding ermöglicht horizontale Skalierung„.
Konkret zeigen wir Schritt für Schritt, wie unser Nearshored DevOps-Team eine Open-Source-MongoDB-Sharding-Lösung für eine skalierbare, hochverfügbare verteilte Datenbank als Alternative zu einer teuren Unternehmenslizenz konfiguriert hat. Spoiler – das Nettoergebnis für unseren Kunden war eine minimale MongoDB-Unternehmenslizenz-Ersparnis von 100.000 Euro pro Jahr. Jedes Jahr.
Wir erläutern Ihnen nicht nur den Anwendungsfall (unser Kunde SolarLog ist ein führendes PV-Energiemanagementsystem), der unsere Entscheidung für die Verwendung von Open-Source-MongoDB-Code begründet, sondern beschreiben auch Schritt für Schritt den Konfigurationsprozess.
MongoDB – Auf der Suche nach dem Heiligen Gral einer automatisierten, selbstheilenden und skalierbaren Datenbanklösung
Wie effektiv Unternehmen und Organisationen Daten nutzen, ist die Grundlage für ihren nachhaltigen Erfolg und ihre Wettbewerbsfähigkeit in der heutigen Welt. Dabei kommt es auf drei Dinge an:
- Datenerfassung
- Datenspeicherung und -verfügbarkeit
- Datenanalyse
Datenbanktechnologien wie MongoDB konzentrieren sich auf Nummer 2. Software-Ingenieure haben sich seit den 1970er Jahren und dem Aufkommen der relationalen SQL-Datenbanken (zuerst von IBM als „System R“-Prototyp entwickelt und 1979 von Oracle kommerzialisiert) mit den Herausforderungen bei der Entwicklung autonomer, selbst wiederherstellbarer und skalierbarer Datenbanksysteme auseinandergesetzt.
In den 1990er Jahren erschienen die objektorientierten Datenbanken, die zu NoSQL-Implementierungen führten, und dieses Format dominiert heute die Massenspeicherung von Daten im Internet. Das ursprüngliche Problem bleibt jedoch bestehen. Mit dem Aufkommen von Cloud Computing und der Verbreitung von IoT-Hardware sind Datenbanktechnologien und -systeme wichtiger denn je. Denn Daten als Währung bilden die Grundlage der digitalen Wirtschaft.
Die wichtigsten Kategorien von NoSQL-Datenbanken sind:
- Key-Values Stores
- Wide-Column Stores
- Document Stores
- Graph Databases
- Und Search Engines
Wir konzentrieren uns hier auf Dokumentenspeicher-Datenbanken, die Daten in Form von JSON-Dokumenten speichern. Für Dokumentenspeicher ist kein festes Schema erforderlich, und die Datenstruktur kann von Dokument zu Dokument variieren. Dokumentendatenbanken verwenden dasselbe Dokumentenmodellformat, das auch in ihrem Anwendungscode verwendet wird, was es Softwareentwicklern erleichtert, die Daten in einer Datenbank zu speichern und abzufragen.
Wie von AWS erklärt:
“Die flexible, halbstrukturierte und hierarchische Natur von Dokumenten und Dokumentendatenbanken ermöglicht es ihnen, sich mit den Anforderungen der Anwendungen weiterzuentwickeln. Das Dokumentenmodell eignet sich gut für Anwendungsfälle wie Kataloge, Benutzerprofile und Content-Management-Systeme, bei denen jedes Dokument einzigartig ist und sich mit der Zeit weiterentwickelt. Dokumentendatenbanken ermöglichen eine flexible Indizierung, leistungsstarke Ad-hoc-Abfragen und Analysen über Dokumentensammlungen.”.
MongoDB, ein Open-Source-Projekt, das auch als Unternehmenslösung verfügbar ist, hat sich zu einer führenden Datenbanktechnologie für Dokumentenspeicher entwickelt, die besonders häufig in einer IoT-Umgebung eingesetzt wird.
Zu den Open-Source-Alternativen zu MongoDB gehören unter anderem CouchDB, Apache Cassandra und PostgreSQL sowie Cloud-Anbieter wie DynamoDB von AWS und AmazonDocumentDB (das mit MongoDB kompatibel ist und es in einer AWS-Umgebung unterstützen kann).
MongoDB Shards und Sharded Clusters
In MongDB werden große Datensätze durch Sharding in kleinere Teilmengen aufgeteilt, die über mehrere Instanzen verteilt sind. Diese mehreren kleineren Datensätze werden als Shards bezeichnet, die zusammen als ein großer clusterbasierter Datensatz arbeiten.
Ab MongoDB 3.6 (der neuesten Version von MongoDB 4.4) werden Shards als Replikatsatz bereitgestellt, der die für moderne Datenbanktechnologien wichtige Redundanz und Hochverfügbarkeit bietet. Shards werden von Benutzern oder Anwendungen nur für lokale Wartungs- und Verwaltungsvorgänge direkt angesprochen.
Eine Abfrage an einen einzelnen Shard gibt nur die Teilmenge der Daten zurück, die sich auf diesem Shard befinden. Bei Operationen auf Clusterebene, wie z. B. Lese- oder Schreibvorgängen, muss der Benutzer oder die Anwendung eine Verbindung zu den Mongos herstellen. Die Technologie garantiert nicht, dass zwei zusammenhängende Datenpakete auf einem einzigen Shard gespeichert werden können.
Sharding aufgeschlüsselt
Schauen wir uns die Komponenten der MongDB-Sharding-Architektur genauer an:
Primary Shard
Jede einzelne Datenbank in einem Sharded-Cluster ist um einen primären Shard zentriert. Der primäre Shard enthält alle nicht gesplitteten Sammlungen der Cluster-Datenbank. Der primäre Shard einer Datenbank ist nicht mit dem primären Shard in einem Replikatsatz verbunden.
Quelle: MongoDB
Mongos
Bei der Erstellung einer neuen Datenbank wird der primäre Shard von den Mongos als derjenige ausgewählt, der die geringste Datenmenge im Cluster enthält. Die Mongos identifizieren den primären Shard anhand des Feldes totalSize, das vom Befehl listDatabase zurückgegeben wird.
Die Schnittstelle zwischen den Client-Anwendungen und dem Shard-Cluster wird von den Mongos-Instanzen bereitgestellt, die Abfragen und Schreibvorgänge an die Shards weiterleiten. Aus Sicht einer Anwendung verhält sich eine Mongos-Instanz genau wie jede andere MongoDB-Instanz.
Ändern des primären Shards in einer Datenbank
Es ist möglich, den Shard, der einer Datenbank als primärer Shard zugewiesen ist, zu ändern, allerdings kann der Migrationsprozess einige Zeit in Anspruch nehmen, während der auf die mit der Datenbank verbundenen Sammlungen nicht zugegriffen werden sollte. Zu diesem Zweck wird der Befehl movePrimary ausgeführt.
Vor der Migration auf einen neuen primären Shard ist zu bedenken, dass größere Datensammlungen, die übertragen werden, den Betrieb eines Clusters beeinträchtigen können. Berücksichtigen Sie dies und die Netzwerkauslastung.
Bei der Bereitstellung eines neuen Sharded-Clusters mit Shards, die zuvor als Replikatsätze verwendet wurden, befinden sich die vorhandenen Datenbanken weiterhin auf ihren ursprünglichen Replikatsätzen. Datenbanken, die zu einem späteren Zeitpunkt erstellt werden, können sich auf jedem beliebigen Shard des Clusters befinden.
Shard Status
Um einen Überblick über einen Cluster zu erhalten, verwenden Sie die Methode sh.status() in der mongo shell. Der Bericht zeigt den primären Shard der Datenbank sowie die Verteilung der Datenchunks auf die Shards eines Clusters.
Sharded Cluster Security
Die Sicherheit innerhalb des Clusters wird aufrechterhalten und der unbefugte Zugriff von Komponenten wird durch die Verwendung der internen/Mitgliedschaftsauthentifizierung blockiert. Die interne Authentifizierung kann nur durchgesetzt werden, wenn jeder Mongode in einem Cluster mit den entsprechenden Sicherheitseinstellungen gestartet wird.
Shard Local Users
Die rollenbasierte Zugriffskontrolle (Role-Based Access Control, RBAC) wird auf einzelnen Shards unterstützt und schränkt den unbefugten Zugriff auf die darauf befindlichen Daten sowie die Operationen ein. Um RBAC durchzusetzen, sollte jeder Mongo im Replikatsatz mit der Option -auth initiiert werden.
Jeder Shard hat seine eigenen shard-lokalen Benutzer, die nicht auf anderen Shards oder zur Verbindung mit dem Cluster über einen Mongo verwendet werden können.
Warum Open Source MongoDB mit Sharding unsere Datenbanklösung ist
Unser Kunde SolarLog ist weltweit führend in der Innovation von Software und IoT-Geräten für die Überwachung und Verwaltung von Photovoltaikanlagen. Die Lösungen des Unternehmens werden weltweit von 327.313 PV-Anlagen in 138 Ländern genutzt. Das Unternehmen betreibt eine große Anzahl von IoT-Geräten, die die Daten der Solarenergieanlagen sammeln, deren Leistung die Produkte und Lösungen des Unternehmens optimieren sollen.
Nach der teilweisen Verarbeitung mussten diese großen und wachsenden Datenströme effizient gespeichert und einfach und zuverlässig zugänglich gemacht werden. Skalierbarkeit war eine Voraussetzung, ebenso wie die Fähigkeit zur Selbstheilung. Die Last musste auf die Clusterknoten verteilt werden, um eine hohe Verfügbarkeit und Wiederherstellbarkeit zu gewährleisten.
Unser Team entschied sich für die Entwicklung der Datenbank unter Verwendung von Open Source MongoDB Sharding. Die einfache Alternative wäre eine MongoDB-Unternehmenslizenz gewesen. Diese hätte jedoch Kosten in Höhe von 100.000 € pro Jahr verursacht, ohne Berücksichtigung der Serverkosten.
Wir waren zuversichtlich, dass eine Konfiguration, die den Open-Source-Code von MongoDB und Sharding zur effektiven Verteilung auf Knoten-Cluster nutzt, die Anforderungen des Projekts vollständig erfüllen würde, und machten uns an die Umsetzung.
Problemlösung – Was wir bei der Konfiguration unserer MongoDB-Sharding-Lösung gelernt haben
Kein Projekt, das eine relativ komplexe benutzerdefinierte Architektur und Entwicklung beinhaltet, wird erfolgreich durchgeführt, ohne dass Probleme auftauchen. Diese spezielle Datenbanklösung bildete da keine Ausnahme. Ursprünglich wurde ein falscher Ansatz für die Erstellung von Backups gewählt. In der endgültigen Version der Lösung wurde das Schema so angepasst, dass Schnappschüsse des Dateisystems erstellt wurden, wobei die Datenbankeinträge in dem Moment gesperrt wurden, in dem die Schnappschüsse erstellt wurden. Meinste ich
MongoDB Sharding-Cluster-Konfiguration: Schritt-für-Schritt-Einrichtung
In unserer Konfiguration werden wir das folgende Schema verwenden:
Der Ausgangspunkt ist die Installation der mongosb-Daemons auf den Config-Servern
config of the first CFG replica set server for mongo
systemLog: destination: file logAppend: true path: /var/log/mongodb/mongod.log storage: dbPath: /var/lib/mongo journal: enabled: true processManagement: fork: true pidFilePath: /var/run/mongodb/mongod.pid timeZoneInfo: /usr/share/zoneinfo net: port: 27017 bindIp: mongos-cfg1 replication: oplogSizeMB: 10240 replSetName: "replconfig01" sharding: clusterRole: configsvr
Für die anderen beiden cfg-Server ist alles ähnlich, wir ändern nur bindIP
Wenn Sie kurze Namen von Clustermitgliedern verwenden, geben Sie diese in der Datei /etc/hosts an
Wir verbinden uns mit unserem ersten Server mongodb-cfg1 und erstellen ein replicaset
mongo --host mongos-cfg1 --port 27017
Befehl ausführen;
rs.initiate( { _id: "replconfig01", configsvr: true, members: [ { _id : 0, host : "mongos-cfg1:27017" }, { _id : 1, host : "mongos-cfg2:27017" }, { _id : 2, host : "mongos-cfg3:27017" } ] } )
In der Ausgabe „ok“: 1 – bedeutet die erfolgreiche Ausführung unseres vorherigen Befehls.
Wir überprüfen den Status aller drei Server, es sollte 1 Primary und 2 Secondary geben, die Befehle zur Überprüfung des Status:
rs.isMaster() rs.status()
Wir konfigurieren unseren Shard für MongoDB, die Konfiguration des ersten Shards:
systemLog: destination: file logAppend: true path: /var/log/mongodb/mongod.log
storage: dbPath: /opt/mongo journal: enabled: true
processManagement: fork: true # fork and run in background pidFilePath: /var/run/mongodb/mongod.pid # location of pidfile timeZoneInfo: /usr/share/zoneinfo
net: port: 27017 bindIp: 0.0.0.0
security: authorization: enabled security: transitionToAuth: false keyFile: /etc/mongo.keyfile replication: replSetName: "rs1" sharding: clusterRole: shardsvr
Generiere keyfile:
openssl rand -base64 756 > /etc/mongo.keyfile chmod 400 /etc/mongo.keyfile
Setzen Sie für das durch dbPath angegebene Mongo-Datenspeicherverzeichnis den richtigen Eigentümer:
chown -R mongod:mongod /opt/mongo/
Wir starten die Dienste und überprüfen, ob die benötigten Daemons auf Port 27017 lauschen.
Wir führen Befehle aus, um das erste Replikat, den ersten Shard, zu initialisieren:
rs.initiate( { _id: "rs1", members: [ { _id : 0, host : "ip_mongo_shard_1_1:27017" }, { _id : 1, host : " ip_mongo_shard_1_2:27017" }, { _id : 2, host : " ip_mongo_shard_1_3:27017" } ] } )
Der letzte und interessanteste Punkt ist die Einrichtung von mongos – ein Router für alle Anfragen an unseren zukünftigen Cluster.
Nachdem das mongod-Paket auf dem zukünftigen Router installiert ist, erstellen wir eine Servicedatei, damit mongos automatisch startet
!!! The mongod service itself must be stopped and excluded from autorun !!!
nano /etc/systemd/system/mongos.service [Unit] Description=High-performance, schema-free document-oriented database After=network.target Documentation=https://docs.mongodb.org/manual [Service] Type=forking User=root Group=root ExecStart=/usr/bin/mongos -f /etc/mongos.conf PIDFile=/var/run/mongos.pid LimitFSIZE=infinity LimitCPU=infinity LimitAS=infinity LimitNOFILE=64000 LimitNPROC=64000 LimitMEMLOCK=infinity TasksMax=infinity TasksAccounting=false [Install] WantedBy=multi-user.target
Den Befehl ausführen um die Liste des Services zu aktualisieren
systemctl daemon-reload systemctl enable mongos
Unsere config Datei für mongos /etc/mongos.conf will be as follows:
:systemLog destination: file logAppend: true path: /var/log/mongodb/mongos.log processManagement: fork: true pidFilePath: /var/run/mongos.pid timeZoneInfo: /usr/share/zoneinfo net: port: 27017 bindIp: 0.0.0.0 maxIncomingConnections: 20000 ipv6: false sharding: configDB: "replconfig01/ mongos-cfg1:27017, mongos-cfg2:27017, mongos-cfg3:27017" security: keyFile: /etc/mongo.keyfile
Auf mongos server wiederholen Sie die Schritte zum Erstellen des keyfile.
Run den Mongos service
systemctl start mongos
Check:
netstat -ntupl | grep mongos tcp 0 0 0.0.0.0:27017 0.0.0.0:* LISTEN 3570/mongos
Also in the log /var/log/mongodb/mongos.log there should be lines with a successful connection to our config replicaset mongo
Successfully connected to mongos-cfg1:27017 Successfully connected to mongos-cfg2:27017 Successfully connected to mongos-cfg3:27017
Der letzte Schliff, die Regierung unserer mongo shard Server im mongos router
Verbinden Sie sich auf dem mongos server mit unserem cluster:
mongo --host mongos --port 27017
und füge unseren shard server hinzu:
sh.addShard("rs1/ ip_mongo_shard_1_1:27017, ip_mongo_shard_1_2:27017, ip_mongo_shard_1_3:27017")
und fügen weitere hinzu, wenn du sie erstellst:
sh.addShard("rs2/ ip_mongo_shard_2_1:27017, ip_mongo_shard_2_2:27017, ip_mongo_shard_2_3:27017") sh.addShard("rs3/ ip_mongo_shard_3_1:27017, ip_mongo_shard_3_2:27017, ip_mongo_shard_3_3:27017") …
MongoDB Sharding Fallstudie: Fazit
Unsere Lösung für SolarLog ist nicht bahnbrechend in dem Sinne, dass wir mit dem Open-Source-Code von MongoDB nichts getan haben, was nicht schon vorher gemacht wurde. Unser MongoDB-Sharding-Ansatz für Cluster entspricht jedoch voll und ganz den Anforderungen des Projekts und zeigt, wie die oft hohen Kosten für Unternehmenslizenzen mit ein wenig Nachdenken und Innovation vermieden werden können.
Die Bezahlung von Unternehmenslösungen kann eine bequeme Option sein, wenn das Geld vorhanden ist und der Business Case den Aufwand rechtfertigt. Aber es ist auch nicht notwendig, insbesondere im Fall von ausgereiften, gut entwickelten und mit Ressourcen ausgestatteten Open-Source-Technologien. Eine Open-Source-Alternative, insbesondere eine, die über die Lebensdauer einer Datenbankarchitektur zu Kosteneinsparungen von bis zu 1 Mio. € führen kann, ist fast immer eine Überlegung und Prüfung wert.