Das Erreichen einer Bereitstellung ohne Ausfallzeiten hat das gleiche Problem angesprochen, aber ich benötige einige Ratschläge zu einer Strategie, die ich in Betracht ziehe.
Kontext
Eine webbasierte Anwendung mit Apache / PHP für die serverseitige Verarbeitung und MySQL DB / Dateisystem für die Persistenz.
Wir bauen derzeit die Infrastruktur. Die gesamte Netzwerkhardware ist redundant, und alle Hauptnetzwerkkabel werden aus Gründen der Fehlertoleranz paarweise miteinander verbunden. Server werden als Hochverfügbarkeitspaare konfiguriert, um Hardwarefehlertoleranz zu gewährleisten. Sie werden sowohl hinsichtlich der Fehlertoleranz der virtuellen Maschine als auch hinsichtlich der allgemeinen Leistung im Lastenausgleich ausgeführt.
Es ist meine Absicht, dass wir Updates ohne Ausfallzeit auf die Anwendung anwenden können. Ich habe große Anstrengungen unternommen, um die Infrastruktur so zu gestalten, dass eine 100% ige Verfügbarkeit gewährleistet ist. Es wäre äußerst enttäuschend, wenn jedes Mal, wenn ein Update angewendet wird, eine Ausfallzeit von 10 bis 15 Minuten auftreten würde. Dies ist besonders wichtig, da ein sehr schneller Release-Zyklus angestrebt wird (manchmal können eine oder mehrere Releases pro Tag erreicht werden).
Netzwerktopologie
Dies ist eine Zusammenfassung des Netzwerks:
Load Balancer
|----------------------------|
/ / \ \
/ / \ \
| Web Server | DB Server | Web Server | DB Server |
|-------------------------|-------------------------|
| Host-1 | Host-2 | Host-1 | Host-2 |
|-------------------------|-------------------------|
Node A \ / Node B
| / |
| / \ |
|---------------------| |---------------------|
Switch 1 Switch 2
And onward to VRRP enabled routers and the internet
Anmerkung: DB-Server verwenden die Master-Master-Replikation
Vorgeschlagene Strategie
Um dies zu erreichen, denke ich derzeit daran, die DB-Schema-Upgrade-Skripte in zwei Teile zu unterteilen. Das Upgrade würde folgendermaßen aussehen:
- Der Webserver auf Knoten A wird offline geschaltet. Der Datenverkehr wird weiterhin vom Webserver auf Knoten B verarbeitet.
- Übergangsschemaänderungen werden auf DB-Server angewendet
- Webserver Eine Codebasis wird aktualisiert, die Caches werden gelöscht und alle anderen Upgrade-Aktionen werden ausgeführt.
- Webserver A wird online geschaltet und Webserver B wird offline geschaltet.
- Die Codebasis von Webserver B wird aktualisiert, die Caches werden gelöscht und alle anderen Aktualisierungsaktionen werden ausgeführt.
- Webserver B wird online geschaltet.
- Die endgültigen Schemaänderungen werden auf die Datenbank angewendet
"Übergangsschema" soll eine versionsübergreifende kompatible Datenbank erstellen. Dies würde hauptsächlich Tabellenansichten verwenden, die das alte Versionsschema simulieren, während die Tabelle selbst in das neue Schema geändert würde. Dadurch kann die alte Version wie gewohnt mit der Datenbank interagieren. Die Tabellennamen würden Schemaversionsnummern enthalten, um sicherzustellen, dass keine Unklarheiten darüber bestehen, in welche Tabelle geschrieben werden soll.
'Letztes Schema' würde die Abwärtskompatibilität aufheben und das Schema aufräumen.
Frage
Kurz gesagt, wird das funktionieren?
genauer:
Wird es Probleme geben, da möglicherweise gleichzeitig Schreibvorgänge zum bestimmten Zeitpunkt der Änderung des Übergangsschemas ausgeführt werden? Gibt es eine Möglichkeit, sicherzustellen, dass die Gruppe von Abfragen, die die Tabelle ändern und die abwärtskompatible Ansicht erstellen, nacheinander ausgeführt wird? Das heißt, alle anderen Abfragen werden im Puffer gehalten, bis die Schemaänderungen abgeschlossen sind. Dies dauert in der Regel nur Millisekunden.
Gibt es einfachere Methoden, die diesen Grad an Stabilität bieten und gleichzeitig Updates ohne Ausfallzeiten ermöglichen? Es ist auch vorzuziehen, die "evolutionäre" Schemastrategie zu vermeiden, da ich nicht an die Abwärtsschemakompatibilität gebunden sein möchte.
quelle
Ihre Strategie ist solide. Ich würde nur anbieten, das "Übergangsschema" zu einem vollständigen Satz von "Transaktionstabellen" zu erweitern.
Bei Transaktionstabellen werden SELECTs (Abfragen) für die normalisierten Tabellen ausgeführt, um die Richtigkeit sicherzustellen. Alle Datenbank-INSERTs, -UPDATES und -DELETEs werden jedoch immer in die denormalisierten Transaktionstabellen geschrieben.
Anschließend wendet ein separater, gleichzeitiger Prozess diese Änderungen (möglicherweise mithilfe gespeicherter Prozeduren) auf die normalisierten Tabellen gemäß den festgelegten Geschäftsregeln und Schemaanforderungen an.
Meistens war dies praktisch augenblicklich. Durch die Trennung der Aktionen kann das System jedoch übermäßige Aktivitäts- und Schemaaktualisierungsverzögerungen berücksichtigen.
Während Schemaänderungen in Datenbank (B) werden Datenaktualisierungen in der aktiven Datenbank (A) in ihre Transaktionstabellen aufgenommen und sofort auf ihre normalisierten Tabellen angewendet.
Beim Wiederherstellen der Datenbank (B) würden die Transaktionen von (A) darauf angewendet, indem sie in die Transaktionstabellen von (B) geschrieben würden. Sobald dieser Teil erledigt ist, kann (A) heruntergefahren und die Schemaänderungen dort angewendet werden. (B) würde das Anwenden der Transaktionen von (A) beenden und gleichzeitig seine Live-Transaktionen bearbeiten, die genau wie (A) in der Warteschlange stehen, und die "Live-Transaktionen" würden auf die gleiche Weise angewendet, wenn (A) erneut aufgerufen wird.
Eine Transaktionstabellenzeile könnte ungefähr so aussehen ...
Die Transaktions- "Tabellen" können tatsächlich Zeilen in einer separaten NoSQL-Datenbank oder sogar sequentielle Dateien sein, abhängig von den Leistungsanforderungen. Ein Bonus ist, dass die Codierung der Anwendung (in diesem Fall der Website) etwas einfacher wird, da nur in die Transaktionstabellen geschrieben wird.
Die Idee folgt denselben Grundsätzen wie die doppelte Buchführung und dies aus ähnlichen Gründen.
Transaktionstabellen sind analog zu einem Buchhaltungsjournal. Die vollständig normalisierten Tabellen sind analog zu einem Buchhaltungs-"Hauptbuch", wobei jede Tabelle einem Buchhaltungs-"Konto" ähnelt.
In der Buchhaltung erhält jede Transaktion zwei Einträge im Journal. Eine für das "belastete" Sachkonto und die andere für das "gutgeschriebene" Konto.
In einem RDBMS erhält ein "Journal" (Transaktionstabelle) einen Eintrag für jede normalisierte Tabelle, die von dieser Transaktion geändert werden soll.
Die DB-Spalte in der obigen Tabelle gibt an, aus welcher Datenbank die Transaktion stammt. Auf diese Weise können die in der Warteschlange befindlichen Zeilen aus der anderen Datenbank herausgefiltert und nicht erneut angewendet werden, wenn die zweite Datenbank wiederhergestellt wird.
quelle