3. Besprechen Sie verteilte Systeme, das Problem der byzantinischen Generäle und Blockchain

Verteilte Systeme und Konsistenzprobleme

Problem der byzantinischen Generäle

Das zuvor besprochene Konsistenzprotokoll hat eine wichtige Voraussetzung: Jeder Knoten ist vertrauenswürdig und alle halten sich strikt an dieselben Regeln. Diese Bedingung kann im unternehmensinternen Netzwerk grundsätzlich als erfüllt angesehen werden. Was aber passiert, wenn diese Bedingung nicht erfüllt ist? Unter der Annahme, dass einige Knoten im Netzwerk böswillig sind und nicht nur das Protokoll nicht einhalten, sondern auch absichtlich Probleme verursachen (z. B. wahlloses Senden von Nachrichten), können andere normale Knoten dann trotzdem reibungslos funktionieren?

In der Theorie verteilter Systeme wird dieses Problem in ein berühmtes Problem abstrahiert – das Problem der byzantinischen Generäle . Diese Frage wurde vom berühmten Leslie Lamport, dem Autor von Paxos, aufgeworfen. Gleichzeitig war Lamport 2013 auch Gewinner des Turing Award.

  • Dies beginnt mit einer Geschichte. Mehrere Armeen des Byzantinischen Reiches griffen außerhalb der feindlichen Stadt an, trennten sich dann und stationierten sich.
  • Jede Armee wurde von einem byzantinischen General angeführt. Um einen einheitlichen Schlachtplan zu formulieren, muss jeder General über Boten mit anderen Generälen kommunizieren.
  • Allerdings könnte es unter den byzantinischen Generälen Verräter gegeben haben. Der Zweck dieser verräterischen Generäle besteht darin, andere loyale Generäle daran zu hindern, einen vereinbarten Schlachtplan zu erreichen.
  • Zu diesem Zweck dürfen sie alles tun, zum Beispiel Absprachen treffen, absichtlich falsche Nachrichten verbreiten oder überhaupt keine Nachrichten verbreiten.

Schauen wir uns ein einfaches Beispiel an. Angenommen, es gibt fünf Generäle, und sie stimmen darüber ab, ob sie angreifen oder sich zurückziehen. Zwei von ihnen meinten, wir sollten angreifen, und zwei meinten, wir sollten uns zurückziehen. Zu diesem Zeitpunkt waren die Stimmen für Angriff und Rückzug 2:2 unentschieden. Der fünfte General war zufällig ein Verräter. Er sagte den ersten beiden Generälen, dass sie angreifen sollten, aber sagte den letzten beiden Generälen, dass sie sich zurückziehen sollten. Infolgedessen beschlossen die ersten beiden Generäle schließlich anzugreifen, aber die letzten beiden Generäle entschieden sich zurückziehen. Es gab keinen vereinbarten Schlachtplan.

Dieses Problem ist offensichtlich schwieriger als das Konsistenzproblem in einer vertrauenswürdigen Umgebung, das wir im vorherigen Kapitel besprochen haben. Um dieses Problem zu lösen, hoffen wir, einen Algorithmus zu finden, der sicherstellt, dass wir in Anwesenheit von Verrätern dennoch die folgenden Ziele erreichen können:

  • A. Alle loyalen Generäle erhielten den gleichen (einstimmigen) Schlachtplan . Zum Beispiel beschließen sie alle, anzugreifen oder sich alle zurückzuziehen, anstatt dass einige Generäle denken, sie sollten angreifen, während andere Generäle sich für den Rückzug entscheiden.
  • B. Ein loyaler General erhält nicht nur den gleichen Schlachtplan, sondern stellt auch sicher, dass der Schlachtplan, den er erhält, vernünftig ist . Beispielsweise war ein Angriff ursprünglich ein vorteilhafterer Schlachtplan, aber aufgrund der Behinderung durch die Verräter wurde schließlich der Plan geschmiedet, sich gemeinsam zurückzuziehen. Auf diese Weise kann unser Algorithmus als gescheitert angesehen werden.

Es ist ersichtlich, dass das obige Ziel A relativ klar ist. Zumindest bei einem gegebenen Algorithmus ist es leicht festzustellen, ob dieses Ziel erreicht wurde. Aber Ziel B ist schwer zu erreichen. Ob ein Kampfplan „vernünftig“ ist oder nicht, ist schwer zu definieren. Selbst wenn es keine Verräter gibt, sind loyale Generäle möglicherweise nicht unbedingt in der Lage, einen vernünftigen Plan zu formulieren. Dabei handelt es sich um ein sehr wichtiges Thema in der wissenschaftlichen Forschung. Wenn eine Sache formal nicht klar definiert werden kann, ist es unmöglich, sie zu untersuchen, und die Angelegenheit selbst kann nicht auf wissenschaftliche Ebene gelangen. Einer seiner herausragenden Beiträge zu Lamports Studie zum Problem der byzantinischen Generäle besteht darin, dass er dieses scheinbar schwer zu definierende Problem geschickt auf ein Problem reduzierte, das in mathematischer Sprache genau beschrieben werden kann. Werfen wir einen Blick darauf, wie dieser Prozess funktioniert.

Betrachten wir zunächst den Prozess, mit dem Generäle Schlachtpläne formulieren (vorausgesetzt, es gibt keine Verräter). Jeder General gibt auf der Grundlage seiner eigenen Beobachtungen der Gefechtssituation seinen empfohlenen Schlachtplan vor – ob Angriff oder Rückzug. Dies wird als Gefechtsvorschlag bezeichnet. Anschließend übermittelte jeder General jedem anderen General seinen Kriegsvorschlag per Kurier. Da nun jeder General die Schlachtvorschläge anderer Generäle sowie seine eigenen Schlachtvorschläge kennt, muss er auf der Grundlage all dieser Informationen einen endgültigen Schlachtplan erstellen. Um es klarer auszudrücken, nummerieren wir jeden General mit 1, 2, …, n, und die von jedem General vorgebrachten Kampfvorschläge werden als v(1), v(2), …, v(n) aufgezeichnet. Insgesamt gibt es n Werte, von denen einige „Angriff“ und einige „Rückzug“ darstellen. Nachdem der Bote die Nachricht überbracht hatte, sah jeder General die gleiche Abfolge von Kampfvorschlägen v(1), v(2), …, v(n). Natürlich wurde einer davon vom aktuellen General selbst vorgeschlagen. Solange dann jeder General die gleiche Methode verwendet und alle Informationen v(1), v(2), ..., v(n) zusammenfasst, kann derselbe endgültige Schlachtplan erhalten werden. Eine leicht vorstellbare Methode ist beispielsweise die Abstimmungsmethode, bei der über verschiedene Kampfvorschläge in v(1), v(2), ..., v(n) abgestimmt und schließlich derjenige mit ausgewählt wird die meisten Stimmen als endgültiger Kampfplan .

Natürlich ist der auf diese Weise erhaltene endgültige Kampfplan nicht garantiert der beste, aber er sollte der beste sein, den wir machen können. Wir gehen immer noch davon aus, dass es unter den Generälen keine Verräter gibt. Wir haben festgestellt, dass die Anforderungen für die oben genannten Ziele A und B angemessen „gesenkt“ werden können: Wir konzentrieren uns nicht mehr darauf, ob die Generäle einen endgültigen vereinbarten Kampfplan erreichen können und ob dieser Plan „vernünftig“ ist; wir konzentrieren uns nur auf jedes Ob Der General erhielt genau die gleichen Kampfvorschläge v(1), v(2), …, v(n). Solange die von jedem General erhaltenen Kampfvorschläge genau gleich sind und auf die gleiche Weise zusammengefasst werden, ist es einfach, einen endgültigen, konsistenten Kampfplan zu erhalten . Ob dieser endgültige Schlachtplan der beste ist, hängt von vielen „menschlichen“ Faktoren ab und ist uns egal.

Nun betrachten wir die Anwesenheit eines Verräters unter den Generälen. Der vorherigen Idee folgend, hoffen wir immer noch, dass jeder General genau die gleichen Kampfvorschläge v(1), v(2), …, v(n) erhalten kann. Schauen wir uns nun einen der Werte v(i) genauer an. In der vorherigen Beschreibung stellt er den Kampfvorschlag des i-ten Generals dar. Wenn der i-te General loyal ist, gibt es mit dieser Definition kein Problem. Wenn der i-te General jedoch ein Verräter ist, dann gibt es ein Problem. Warum? Da der Verräter tun und lassen kann, was er will, kann er verschiedenen Generälen unterschiedliche Kampfvorschläge unterbreiten, um die Formulierung des gesamten Kampfplans zu stören. In diesem Fall erhalten verschiedene loyale Generäle möglicherweise unterschiedliche Werte von v(i) vom i-ten General. Auf diese Weise ist die Definition von v(i) falsch und muss geändert werden.

Selbst wenn es Verräter gibt, hoffen wir auf jeden Fall immer noch, dass jeder General letztendlich eine Zusammenfassung basierend auf genau denselben Kampfvorschlägen macht. Diese Kampfvorschläge werden immer noch als v(1), v(2), …, v(n) aufgezeichnet. . Allerdings stellt v(i) hier nicht mehr den Kampfvorschlag des i-ten Generals dar, sondern den i-ten Vorschlag, den jeder General schließlich sieht, nachdem er von einem bestimmten von uns entworfenen Konsensalgorithmus verarbeitet wurde. Zwei Situationen müssen hier besprochen werden. Wenn der i-te General im ersten Fall loyal ist, hoffen wir natürlich, dass v(i) der vom i-ten General gesendete Kampfvorschlag ist. Mit anderen Worten: Wir hoffen, dass nach der Verarbeitung durch den Konsensalgorithmus, wenn der i-te General loyal ist, sein Vorschlag wahrheitsgemäß an andere Generäle weitergegeben werden kann, ohne durch das Verhalten des Verräters gestört zu werden. Dies ist die Voraussetzung für die Möglichkeit, einen „vernünftigen“ Kampfplan zu formulieren. Im zweiten Fall kann der i-te General, wenn er ein Verräter ist, unterschiedliche Vorschläge an verschiedene Generäle senden. Zu diesem Zeitpunkt können wir uns nicht nur seine Seite der Geschichte anhören, sondern hoffen, dass die Generäle nach der Verarbeitung durch den Konsensalgorithmus ihre Meinungen vollständig austauschen und dann auf der Grundlage der von den anderen weitergegebenen Informationen umfassend beurteilen und ein v(i) erhalten Generäle. Ob dieses v(i) angreift oder sich zurückzieht, ist nicht sehr wichtig. Der Schlüssel besteht darin, sicherzustellen, dass jeder General das gleiche v(i) erhält. Nur so können die Generäle nach Zusammenfassung aller v(1), v(2), ..., v(n) einen endgültigen und völlig konsistenten Schlachtplan erhalten.

Basierend auf der obigen Analyse stellen wir fest, dass wir in beiden Fällen nur darauf achten müssen, wie der Vorschlag eines einzelnen Generals (d. h. des i-ten Generals) anderen Generälen mitgeteilt wird. Der Punkt ist endlich da! An diesem Punkt können wir das ursprüngliche Problem auf ein Unterproblem reduzieren. Dieses Unterproblem ist das Problem, das Leslie Lamport in seinem Aufsatz tatsächlich „Problem der byzantinischen Generäle“ nannte. Bei diesem Problem konzentrieren wir uns nur auf einen einzelnen General, der Befehle sendet, und nennen ihn den kommandierenden General, während andere Generäle, die Befehle entgegennehmen, Leutnants genannt werden. Das Folgende ist eine genaue Beschreibung des „byzantinischen Generalsproblems“.

Ein Kommandant sendet einen Befehl an n-1 Leutnants. Wie können wir die folgenden zwei Bedingungen sicherstellen:

  • (IC1) Alle loyalen Leutnants erhalten letztendlich die gleichen Befehle.
  • (IC2) Wenn der General loyal ist, akzeptieren alle loyalen Leutnants Befehle des Generals.

Dies entspricht tatsächlich den beiden zuvor besprochenen Situationen. Wenn der General loyal ist, stellt Bedingung IC2 sicher, dass der Befehl wahrheitsgetreu ausgeführt wird, und Bedingung IC1 ist zu diesem Zeitpunkt natürlich erfüllt. Wenn der General ein Verräter ist, ist Bedingung IC2 bedeutungslos, und Bedingung IC1 garantiert dies, selbst wenn der General Verräter ist wird jeden Leutnant kontrollieren. Erteilen Sie unterschiedliche Befehle und jeder Leutnant hat am Ende immer noch einheitliche Befehle.

Es gibt zwei Dinge, die hier für Verwirrung sorgen können.

Erstens fragen sich manche vielleicht: Kann der General immer noch ein Verräter sein? Die Generäle sind alle Verräter, was können wir also sonst tun? Tatsächlich ist dies der Fall. Dieses „Problem der byzantinischen Generäle“ ist nur ein Teilproblem des ursprünglichen Problems. Wenn n Generäle durch Weitergabe von Nachrichten über einen Schlachtplan entscheiden, kann dieser in n „byzantinische Generäle“ zerlegt werden, d. h. jeder General ist der Obergeneral und die verbleibenden n-1 Generäle sind die Adjutanten. Wenn es einen Algorithmus gibt, der das „Problem der byzantinischen Generäle“ lösen kann, dann ermöglicht die gleichzeitige Ausführung von n Algorithmusinstanzen jedem General, genau die gleiche Folge von Kampfvorschlägen zu erhalten, d. h. v(1), v(2 ), die wir bereits erwähnt haben, …, v(n). Schließlich fasst jeder General v(1), v(2), ..., v(n) mit derselben Methode (z. B. Mehrheitsentscheidung) zusammen, um den endgültigen Schlachtplan zu erhalten.

Zweitens: Wenn der General ein Verräter ist, kann er verschiedene Befehle an verschiedene Leutnants senden. Wie ist es möglich, dass jeder Leutnant am Ende immer noch denselben Befehl erhält? Genau das muss der Algorithmus lösen. Tatsächlich ist dies leicht zu erklären (wir haben diese Idee auch bereits erwähnt): Da der General unterschiedliche Befehle an verschiedene Adjutanten senden kann, kann der Adjutant die vom General gesendeten Befehle nicht direkt übernehmen, sondern muss sich auch die von ihm übermittelten Befehle ansehen andere Adjutanten. Wie lautet der Befehl des Generals? Nachdem ein Adjutant dann die von allen Adjutanten übermittelten Befehle (plus die direkt vom General gesendeten Befehle) kombiniert hat, kann er umfassendere Informationen erhalten und ein einheitliches Urteil fällen (in der Praxis handelt es sich um einen iterativen Prozess).

Okay, wir haben so viel Platz aufgewendet und endlich das „Problem der byzantinischen Generäle“ selbst klar beschrieben. Das ist tatsächlich der schwierigste Teil. Wie wir im vorherigen Kapitel erwähnt haben, ist das Verständnis der Frage selbst wichtiger als das Verständnis der Antwort auf die Frage. Solange das Problem selbst klar analysiert ist, ist es nur eine Frage der Details, wie ein Algorithmus entworfen werden kann, der es lösen kann. Wir werden hier nicht auf die Details des Algorithmus eingehen. Interessierte Leser können die folgenden Artikel lesen:

Wir erwähnen hier nur die Schlussfolgerungen des in der Arbeit dargelegten Algorithmus.

Unter Verwendung verschiedener Nachrichtenmodelle gibt es unterschiedliche Lösungen für das „Problem der byzantinischen Generäle“.

  • Wenn mündliche Nachrichten zwischen Generälen verwendet werden, d. h. die Nachrichten können bei der Weiterleitung manipuliert werden, sind für den Umgang mit m Verrätern mindestens 3 Mio. + 1 Generäle erforderlich (von denen mindestens 2 Mio. + 1 Generäle loyal sind). .
  • Wenn Generäle signierte Nachrichten verwenden, d. das heißt, das heißt, mindestens 2 loyale Generäle (wenn es nur 1 loyalen General gibt, ist diese Frage offensichtlich bedeutungslos). Diese Situation bedeutet praktisch keine Begrenzung der Zahl loyaler Generäle.

Fehlertoleranz

Wie bereits erwähnt, laufen die von Paxos repräsentierten verteilten Konsensprotokolle in einer vertrauenswürdigen Umgebung. Beim „Problem der byzantinischen Generäle“ gibt es bösartige Knoten im Netzwerk. Daher können wir leicht auf eine Idee kommen: Ist Paxos eine Sonderfalllösung des „Problems der byzantinischen Generäle“, wenn die Anzahl der Verräter Null ist?

Es stimmt tatsächlich etwas nicht, wenn man es so betrachtet. Im „Problem der byzantinischen Generäle“ sind neben den Verrätern die übrigen loyale Generäle. Das Wort „Loyalität“ impliziert tatsächlich eine Bedeutung: Er kann normal arbeiten (das heißt, Sie können jederzeit über Nachrichten mit ihm interagieren). Warum sagst du das? Wir wissen, dass ein Verräter alles tun kann, vom Versenden falscher Nachrichten bis hin zum Versenden überhaupt keiner Nachrichten. „Keine Nachricht gesendet“ bedeutet, dass es nicht ordnungsgemäß funktioniert oder dass eine Fehlfunktion aufgetreten ist. Daher sollten nicht nur vorsätzliche böswillige Handlungen, sondern auch einfache Fehlfunktionen als Handlungen von Verrätern eingestuft werden. Für andere Generäle macht das keinen Unterschied.

Nach diesem Verständnis ist das Wort „Loyalität“ nicht sehr passend. Die Anzahl der Verräter ist Null, was bedeutet, dass jeder Knoten im Netzwerk normal funktioniert. Aber Paxos ist auch auf Fehlertoleranz ausgelegt. Wie wir bereits besprochen haben, kann Paxos immer noch normal funktionieren, wenn einige Knoten im Netzwerk ausfallen (z. B. aufgrund von Ausfallzeiten). Es ist ersichtlich, dass Paxos nicht als Sonderfalllösung des „Problems der byzantinischen Generäle“ angesehen werden kann, wenn die Anzahl der Verräter Null ist.

Wie sollten wir also die Beziehung zwischen dem „Problem der byzantinischen Generäle“ und verteilten Konsensalgorithmen wie Paxos sehen? Wir können es anhand der Stärke der Fehlertoleranz analysieren.

Im Allgemeinen muss beim Entwurf eines Computersystems, egal ob es so klein wie ein Chip oder so groß wie ein verteiltes Netzwerk ist, ein gewisses Maß an Fehlertoleranz berücksichtigt werden. Aufgrund der unterschiedlichen Art der Fehler lassen sich diese jedoch in zwei Kategorien einteilen:

  • Byzantinische Schuld. Solche Fehler erscheinen verschiedenen Beobachtern inkonsistent.
  • Nichtbyzantinischer Fehler. Im wahrsten Sinne des Wortes bezieht es sich auf andere Fehler, die nicht in die vorherige Kategorie fallen.

Die Bedeutung dieser beiden Arten von Fehlern ist nicht so leicht zu verstehen, wie sie auf dem Papier erscheint.

Lassen Sie uns zunächst über den byzantinischen Fehler sprechen. Im „Problem der byzantinischen Generäle“ fällt das böswillige Verhalten des Verräters sicherlich in diese Fehlerkategorie. Ein Verräter kann in den Augen verschiedener Generäle völlig widersprüchliche Kriegsvorschläge unterbreiten. In Computersystemen können auch ausgefallene Knoten oder Komponenten ein inkonsistentes Verhalten aufweisen. Dies ist zwar nicht bösartig, fällt aber ebenfalls in diese Fehlerkategorie. Wenn der Kanal beispielsweise instabil ist, treten zufällige Fehler in Nachrichten auf, die von Knoten an andere Knoten gesendet werden, oder die Nachrichten sind beschädigt. Ein weiteres Beispiel: Im Datenbanksystem wurden die Daten nach dem Festschreiben offensichtlich mit der Festplatte synchronisiert (durch fsync des Betriebssystems), aber aufgrund eines plötzlichen Stromausfalls und anderer Gründe konnten die Daten nicht wirklich erfolgreich auf die Festplatte heruntergeladen werden am Ende, und es kam sogar zu Datenverwirrungen.

Schauen wir uns noch einmal die nicht-byzantinischen Fehler an. Lamport verwendete in einer seiner Arbeiten über Paxos auch den Begriff „nicht-byzantinisch“ (siehe „Paxos Made Simple“). Aber die Benennung dieses Wortes ist tatsächlich etwas schwer zu verstehen. Wenn in einem verteilten System ein Knoten ausfällt oder das Netzwerk blockiert ist, können einige Knoten nicht funktionieren. Andere Knoten können diese beiden Situationen eigentlich nicht unterscheiden. Ihrer Ansicht nach stellen sie lediglich fest, dass ein bestimmter Knoten vorübergehend nicht erreichbar ist (d. h. der Empfang von Nachrichten ist abgelaufen). Es lässt sich nicht unterscheiden, ob ein Problem mit dem Knoten selbst vorliegt, das Netzwerk ausgefallen ist oder die Nachricht stark verzögert ist. Darüber hinaus kann sich der Knoten nach einer Weile wieder erholen (entweder von selbst oder durch manuelles Eingreifen). Mit anderen Worten: Für den Knoten, bei dem dieser Fehler auftritt, können wir zwar keine Nachrichten von ihm empfangen, aber wir erhalten keine Fehlermeldungen von ihm. Im Gegenteil: Solange eine Nachricht von ihr empfangen wird, ist die Nachricht selbst „treu“.

Es ist ersichtlich, dass byzantinische Fehler eine stärkere Fehlerart darstellen. Beim „Problem der byzantinischen Generäle“ sendet der Verräter inkonsistente Kriegsvorschläge, was ein byzantinischer Fehler ist, und sendet keine Nachrichten, was ein nicht-byzantinischer Fehler ist. Daher kann der Algorithmus, der das „Problem der byzantinischen Generäle“ löst, sowohl byzantinische als auch nicht-byzantinische Fehler verarbeiten. Das klingt vielleicht etwas seltsam, aber das ist nur eine Frage der Benennung.

Kurz gesagt, die Lösung des „Problems der byzantinischen Generäle“ sollte der stärkste Typ eines verteilten Konsensalgorithmus sein, der theoretisch mit allen Fehlern umgehen kann. Paxos kann nur nicht-byzantinische Fehler verarbeiten. Diese Art der Fehlertoleranz, die mit byzantinischen Fehlern umgehen kann, wird üblicherweise als „byzantinische Fehlertoleranz“ oder kurz BFT bezeichnet.

Je suppose que tu aimes

Origine blog.csdn.net/weixin_46645965/article/details/135283138
conseillé
Classement