CodeGym/Java-Kurse/All lectures for DE purposes/So implementieren Sie ACID in einer Anwendung: Übung

So implementieren Sie ACID in einer Anwendung: Übung

Verfügbar

8.1 Transaktions-IDs

Es wird als XID oder TxID bezeichnet (wenn es einen Unterschied gibt, sagen Sie es mir). Zeitstempel können als TxID verwendet werden, was in die Hände spielen kann, wenn wir alle Aktionen auf einen bestimmten Zeitpunkt zurücksetzen möchten. Das Problem kann auftreten, wenn der Zeitstempel nicht granular genug ist – dann können Transaktionen die gleiche ID erhalten.

Daher besteht die zuverlässigste Option darin, eindeutige UUID-Produkt-IDs zu generieren. In Python ist das ganz einfach:

>>> import uuid 
>>> str(uuid.uuid4()) 
'f50ec0b7-f960-400d-91f0-c42a6d44e3d0' 
>>> str(uuid.uuid4()) 
'd15bed89-c0a5-4a72-98d9-5507ea7bc0ba' 

Es besteht auch die Möglichkeit, einen Satz transaktionsdefinierender Daten zu hashen und diesen Hash als TxID zu verwenden.

8.2 Wiederholungsversuche

Wenn wir wissen, dass eine bestimmte Funktion oder ein bestimmtes Programm idempotent ist, bedeutet dies, dass wir versuchen können und sollten, den Aufruf im Fehlerfall zu wiederholen. Und wir müssen nur darauf vorbereitet sein, dass bei manchen Vorgängen ein Fehler auftritt – angesichts der Tatsache, dass moderne Anwendungen über das Netzwerk und die Hardware verteilt sind, sollte der Fehler nicht als Ausnahme, sondern als die Norm betrachtet werden. Der Fehler kann aufgrund eines Serverabsturzes, eines Netzwerkfehlers oder einer Überlastung der Remoteanwendung auftreten. Wie soll sich unsere Anwendung verhalten? Das ist richtig, versuchen Sie, den Vorgang zu wiederholen.

Da ein Codeteil mehr sagen kann als eine ganze Seite mit Wörtern, wollen wir anhand eines Beispiels verstehen, wie der naive Wiederholungsmechanismus idealerweise funktionieren sollte. Ich werde dies anhand der Tenacity-Bibliothek demonstrieren (sie ist so gut gestaltet, dass das Beispiel Ihnen zeigen sollte, wie Sie den Wiederholungsmechanismus entwerfen können, selbst wenn Sie sie nicht verwenden möchten):

import logging
import random
import sys
from tenacity import retry, stop_after_attempt, stop_after_delay, wait_exponential, retry_if_exception_type, before_log

logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
logger = logging.getLogger(__name__)

@retry(
	stop=(stop_after_delay(10) | stop_after_attempt(5)),
	wait=wait_exponential(multiplier=1, min=4, max=10),
	retry=retry_if_exception_type(IOError),
	before=before_log(logger, logging.DEBUG)
)
def do_something_unreliable():
	if random.randint(0, 10) > 1:
    	raise IOError("Broken sauce, everything is hosed!!!111one")
	else:
    	return "Awesome sauce!"

print(do_something_unreliable.retry.statistics)

> Nur für den Fall, ich sage: \@retry(...) ist eine spezielle Python-Syntax namens „Decorator“. Es handelt sich lediglich um eine retry(...)-Funktion, die eine andere Funktion umschließt und vor oder nach ihrer Ausführung etwas ausführt.

Wie wir sehen, können Wiederholungsversuche kreativ gestaltet werden:

  • Sie können die Versuche nach Zeit (10 Sekunden) oder Anzahl der Versuche (5) begrenzen.
  • Kann exponentiell sein (d. h. 2 ** eine steigende Zahl n ). oder auf andere Weise (z. B. behoben), um die Zeit zwischen einzelnen Versuchen zu verlängern. Die exponentielle Variante wird „Staukollaps“ genannt.
  • Sie können es nur bei bestimmten Fehlertypen (IOError) erneut versuchen.
  • Wiederholungsversuchen können einige spezielle Einträge im Protokoll vorausgehen oder abgeschlossen werden.

Nachdem wir nun den Young-Fighter-Kurs abgeschlossen haben und die Grundbausteine ​​kennen, die wir für die Arbeit mit Transaktionen auf der Anwendungsseite benötigen, machen wir uns mit zwei Methoden vertraut, mit denen wir Transaktionen in verteilten Systemen implementieren können.

8.3 Erweiterte Tools für Transaktionsliebhaber

Ich werde nur ziemlich allgemeine Definitionen geben, da dieses Thema einen separaten großen Artikel verdient.

Zwei-Phasen-Commit (2 Stück) . 2pc besteht aus zwei Phasen: einer Vorbereitungsphase und einer Festschreibungsphase. Während der Vorbereitungsphase werden alle Microservices gebeten, sich auf einige Datenänderungen vorzubereiten, die atomar durchgeführt werden können. Sobald alle bereit sind, werden in der Commit-Phase die eigentlichen Änderungen vorgenommen. Um den Prozess zu koordinieren, wird ein globaler Koordinator benötigt, der die notwendigen Objekte sperrt – das heißt, sie werden für Änderungen unzugänglich, bis der Koordinator sie entsperrt. Wenn ein bestimmter Microservice nicht für Änderungen bereit ist (z. B. nicht antwortet), bricht der Koordinator die Transaktion ab und beginnt mit dem Rollback-Prozess.

Warum ist dieses Protokoll gut? Es sorgt für Atomizität. Darüber hinaus gewährleistet es Isolation beim Schreiben und Lesen. Das bedeutet, dass Änderungen an einer Transaktion für andere nicht sichtbar sind, bis der Koordinator die Änderungen festschreibt. Allerdings haben diese Eigenschaften auch einen Nachteil: Da dieses Protokoll synchron (blockierend) ist, verlangsamt es das System (trotz der Tatsache, dass der RPC-Aufruf selbst recht langsam ist). Und auch hier besteht die Gefahr gegenseitiger Blockaden.

Saga . Bei diesem Muster wird eine verteilte Transaktion durch asynchrone lokale Transaktionen über alle zugehörigen Microservices hinweg ausgeführt. Microservices kommunizieren untereinander über einen Eventbus. Wenn ein Mikrodienst seine lokale Transaktion nicht abschließen kann, führen andere Mikrodienste Ausgleichstransaktionen durch, um die Änderungen rückgängig zu machen.

Der Vorteil von Saga besteht darin, dass keine Objekte blockiert werden. Aber es gibt natürlich auch Nachteile.

Saga ist schwer zu debuggen, insbesondere wenn viele Microservices beteiligt sind. Ein weiterer Nachteil des Saga-Musters besteht darin, dass es keine Leseisolation aufweist. Das heißt, wenn uns die in ACID angegebenen Eigenschaften wichtig sind, dann ist Saga für uns nicht sehr geeignet.

Was sehen wir aus der Beschreibung dieser beiden Techniken? Die Tatsache, dass in verteilten Systemen die Verantwortung für Atomizität und Isolation bei der Anwendung liegt. Das Gleiche passiert, wenn Datenbanken verwendet werden, die keine ACID-Garantien bieten. Das heißt, Dinge wie Konfliktlösung, Rollbacks, Commits und die Freigabe von Speicherplatz fallen auf die Schultern des Entwicklers.

8.4 Woher weiß ich, wann ich ACID-Garantien benötige?

Wenn eine hohe Wahrscheinlichkeit besteht, dass eine bestimmte Gruppe von Benutzern oder Prozessen gleichzeitig an denselben Daten arbeitet .

Entschuldigen Sie die Banalität, aber ein typisches Beispiel sind Finanztransaktionen.

Wenn die Reihenfolge, in der Transaktionen ausgeführt werden, wichtig ist.

Stellen Sie sich vor, dass Ihr Unternehmen im Begriff ist, vom Messenger FunnyYellowChat auf den Messenger FunnyRedChat umzusteigen, da Sie mit FunnyRedChat Gifs versenden können, mit FunnyYellowChat jedoch nicht. Aber Sie wechseln nicht nur den Messenger – Sie migrieren die Korrespondenz Ihres Unternehmens von einem Messenger auf einen anderen. Sie tun dies, weil Ihre Programmierer zu faul waren, Programme und Prozesse irgendwo zentral zu dokumentieren, und stattdessen alles in verschiedenen Kanälen im Messenger veröffentlicht haben. Ja, und Ihre Vertriebsmitarbeiter haben die Einzelheiten der Verhandlungen und Vereinbarungen an derselben Stelle veröffentlicht. Kurz gesagt, das ganze Leben Ihres Unternehmens ist da, und da niemand Zeit hat, das Ganze an einen Dienst zur Dokumentation zu übertragen, und die Suche nach Instant Messengern gut funktioniert, haben Sie sich entschieden, statt den Schutt wegzuräumen, einfach alles zu kopieren Nachrichten an einen neuen Ort. Die Reihenfolge der Nachrichten ist wichtig

Bei der Korrespondenz im Messenger ist übrigens generell die Reihenfolge wichtig, aber wenn zwei Personen gleichzeitig im selben Chat etwas schreiben, dann ist es generell nicht so wichtig, wessen Nachricht zuerst erscheint. Für dieses spezielle Szenario wäre ACID also nicht erforderlich.

Ein weiteres mögliches Beispiel ist die Bioinformatik. Ich verstehe das überhaupt nicht, gehe aber davon aus, dass bei der Entschlüsselung des menschlichen Genoms Ordnung wichtig ist. Allerdings habe ich gehört, dass Bioinformatiker im Allgemeinen einige ihrer Tools für alles nutzen – vielleicht haben sie ihre eigenen Datenbanken.

Wenn Sie einem Benutzer keine veralteten Daten zur Verfügung stellen oder verarbeiten können.

Und wieder - Finanztransaktionen. Ehrlich gesagt fiel mir kein anderes Beispiel ein.

Ausstehende Transaktionen sind mit erheblichen Kosten verbunden. Stellen Sie sich die Probleme vor, die auftreten können, wenn ein Arzt und eine Krankenschwester gleichzeitig eine Patientenakte aktualisieren und die Änderungen des jeweils anderen löschen, da die Datenbank Transaktionen nicht isolieren kann. Das Gesundheitssystem ist neben dem Finanzwesen ein weiterer Bereich, in dem ACID-Garantien tendenziell von entscheidender Bedeutung sind.

8.5 Wann benötige ich ACID nicht?

Wenn Benutzer nur einige ihrer privaten Daten aktualisieren.

Beispielsweise hinterlässt ein Benutzer Kommentare oder Haftnotizen auf einer Webseite. Oder bearbeitet personenbezogene Daten in einem persönlichen Konto bei einem Anbieter beliebiger Dienste.

Wenn Benutzer Daten überhaupt nicht aktualisieren, sondern nur durch neue ergänzen (anhängen).

Zum Beispiel eine Laufanwendung, die Daten zu Ihren Läufen speichert: wie viel Sie gelaufen sind, für welche Zeit, Route usw. Bei jedem neuen Lauf handelt es sich um neue Daten, und die alten werden überhaupt nicht bearbeitet. Vielleicht erhalten Sie auf der Grundlage der Daten Analysen – und für dieses Szenario eignen sich nur NoSQL-Datenbanken.

Wenn die Geschäftslogik nicht die Notwendigkeit einer bestimmten Reihenfolge bestimmt, in der Transaktionen ausgeführt werden.

Für einen Youtube-Blogger, der bei der nächsten Live-Übertragung Spenden für die Produktion neuen Materials sammelt, ist es wahrscheinlich nicht so wichtig, wer ihm wann und in welcher Reihenfolge Geld zugeworfen hat.

Wenn Benutzer mehrere Sekunden oder sogar Minuten lang auf derselben Webseite oder demselben Anwendungsfenster bleiben und daher veraltete Daten sehen.

Theoretisch handelt es sich dabei um beliebige Online-Nachrichtenmedien oder dasselbe Youtube. Oder „Habr“. Wenn es Ihnen egal ist, dass unvollständige Transaktionen vorübergehend im System gespeichert werden, können Sie diese ohne Schaden ignorieren.

Wenn Sie Daten aus vielen Quellen aggregieren und Daten mit hoher Frequenz aktualisieren – zum Beispiel Daten über die Belegung von Parkplätzen in einer Stadt, die sich mindestens alle 5 Minuten ändert, dann wird das theoretisch kein großes Problem darstellen für Sie, wenn die Transaktion für einen der Parkplätze irgendwann nicht zustande kommt. Allerdings kommt es natürlich darauf an, was genau Sie mit diesen Daten machen wollen.

Kommentare
  • Beliebt
  • Neu
  • Alt
Du musst angemeldet sein, um einen Kommentar schreiben zu können
Auf dieser Seite gibt es noch keine Kommentare