
Mein Name ist Vladislav, ich beteilige mich an der Entwicklung von
Tarantool - DBMS und Anwendungsserver in einer Flasche. Und heute werde ich Ihnen erzählen, wie wir die horizontale Skalierung in Tarantool mithilfe des
VShard- Moduls
implementiert haben .
Zunächst eine kleine Theorie.
Es gibt zwei Arten der Skalierung: horizontal und vertikal. Horizontal wird in zwei Typen unterteilt: Replikation und Sharding. Die Replikation wird zum Skalieren von Computern verwendet, das Sharding zum Skalieren von Daten.
Sharding wird in zwei Typen unterteilt: Sharding nach Bereichen und Sharding nach Hashes.
Beim Sharding mit Bereichen berechnen wir aus jedem Datensatz im Cluster einen Shard-Schlüssel. Diese Shard-Schlüssel werden auf eine gerade Linie projiziert, die in Bereiche unterteilt ist, die wir verschiedenen physischen Knoten hinzufügen.
Das Sharding mit Hashes ist einfacher: Von jedem Datensatz im Cluster, den wir als Hash-Funktion betrachten, fügen wir die Einträge mit demselben Wert der Hash-Funktion einem physischen Knoten hinzu.
Ich werde über horizontale Skalierung mit Hash-Sharding sprechen.
Vorherige Implementierung
Das erste horizontale Skalierungsmodul, das wir hatten, war
Tarantool Shard . Dies ist ein sehr einfaches Sharding durch Hashes, bei dem der Shard-Schlüssel aus dem Primärschlüssel aller Einträge im Cluster berücksichtigt wird.
function shard_function(primary_key) return guava(crc32(primary_key), shard_count) end
Aber dann entstand eine Aufgabe, die Tarantool Shard aus drei grundlegenden Gründen nicht bewältigen konnte.
Erstens war die
Lokalität logisch verwandter Daten erforderlich. Wenn Daten logisch verbunden sind, möchten wir sie immer auf demselben physischen Knoten speichern, unabhängig davon, wie sich die Clustertopologie ändert oder der Ausgleich durchgeführt wird. Und Tarantool Shard garantiert dies nicht. Er betrachtet den Hash nur anhand von Primärschlüsseln, und beim Neuausgleich können sogar Datensätze mit demselben Hash für einige Zeit getrennt werden - die Übertragung ist nicht atomar.
Das Problem der fehlenden Lokalität der Daten hat uns am meisten verhindert. Ich werde ein Beispiel geben. Es gibt eine Bank, bei der der Kunde ein Konto eröffnet hat. Konto- und Kundendaten müssen immer physisch zusammen gespeichert werden, damit sie in einer Anfrage gelesen und in einer Transaktion ausgetauscht werden können, beispielsweise beim Überweisen von Geld von einem Konto. Wenn Sie klassisches Sharding mit Tarantool Shard verwenden, unterscheiden sich die Werte der Shard-Funktionen für Konten und Kunden. Daten können sich auf verschiedenen physischen Knoten befinden. Dies erschwert sowohl das Lesen als auch die Transaktionsarbeit mit einem solchen Kunden erheblich.
format = {{'id', 'unsigned'}, {'email', 'string'}} box.schema.create_space('customer', {format = format}) format = {{'id', 'unsigned'}, {'customer_id', 'unsigned'}, {'balance', 'number'}} box.schema.create_space('account', {format = format})
Im obigen Beispiel können die
id
Felder leicht nicht mit Konten und Kunden übereinstimmen. Sie sind über das Kontofeld
customer_id
und
customer_id
id
. Das gleiche
id
Feld würde die Eindeutigkeit des Konto-Primärschlüssels beeinträchtigen. Und auf andere Weise kann Shard nicht scherben.
Das nächste Problem ist das
langsame Resharding . Dies ist das klassische Problem aller Scherben auf Hashes. Unter dem Strich ändern wir normalerweise die Shard-Funktion, wenn wir die Zusammensetzung eines Clusters ändern, da dies normalerweise von der Anzahl der Knoten abhängt. Wenn sich die Funktion ändert, müssen Sie alle Einträge im Cluster durchgehen und die Shard-Funktion erneut neu berechnen. Vielleicht ein paar Notizen übertragen. Und während wir sie übertragen, wissen wir nicht, ob die Daten, die für die nächste eingehende Anforderung benötigt werden, bereits übertragen wurden. Vielleicht werden sie gerade übertragen. Daher ist es während des Resharding erforderlich, dass bei jedem Lesen zwei Shard-Funktionen angefordert werden: die alte und die neue. Anfragen werden doppelt so langsam und für uns war das inakzeptabel.
Ein weiteres Merkmal von Tarantool Shard war, dass bei Ausfall einiger Knoten in den Replikatsätzen eine
schlechte Lesezugriffsfähigkeit angezeigt wird.
Neue Lösung
Um die drei beschriebenen Probleme zu lösen, haben wir
Tarantool VShard erstellt . Der Hauptunterschied besteht darin, dass die Datenspeicherebene virtualisiert wird: Virtuelle Speicher werden über physischen Speichern angezeigt, und Datensätze werden unter ihnen verteilt. Diese Speicher werden Bucket'ami genannt. Der Benutzer muss nicht darüber nachdenken, was und auf welchem physischen Knoten liegt. Bucket ist eine atomare unteilbare Dateneinheit, wie beim klassischen Sharding eines Tupels. VShard speichert immer den gesamten Bucket auf einem physischen Knoten und überträgt beim Resharding alle Daten eines Buckets atomar. Aus diesem Grund wird Lokalität zur Verfügung gestellt. Wir müssen nur die Daten in einen Bucket packen und können immer sicher sein, dass diese Daten zusammen mit allen Änderungen im Cluster vorliegen.

Wie kann ich Daten in einen Eimer legen? In dem Schema, das wir zuvor für den Bankkunden eingeführt haben, fügen wir die
bucket id
gemäß dem neuen Feld zu den Tabellen hinzu. Wenn die verknüpften Daten identisch sind, befinden sich die Datensätze im selben Bucket. Der Vorteil ist, dass wir diese Datensätze mit derselben
bucket id
in verschiedenen Räumen und sogar in verschiedenen Engines speichern können. Die
bucket id
bereitgestellt, unabhängig davon, wie diese Datensätze gespeichert sind.
format = {{'id', 'unsigned'}, {'email', 'string'}, {'bucket_id', 'unsigned'}} box.schema.create_space('customer', {format = format}) format = {{'id', 'unsigned'}, {'customer_id', 'unsigned'}, {'balance', 'number'}, {'bucket_id', 'unsigned'}} box.schema.create_space('account', {format = format})
Warum sind wir so gespannt darauf? Wenn wir klassisches Sharding haben, können sich die Daten über alle physischen Speicher erstrecken, die wir nur haben. Wenn Sie im Beispiel mit der Bank alle Konten eines Kunden anfordern, müssen Sie sich an alle Knoten wenden. Es stellt sich heraus, dass es schwierig ist, O (N) zu lesen, wobei N die Anzahl der physischen Speicher ist. Schrecklich langsam.
Dank Bucket'am und der Lokalität nach
bucket id
wir unabhängig von der Clustergröße immer Daten von einem Knoten in einer Anforderung lesen.

Sie müssen die
bucket id
berechnen und dieselben Werte selbst zuweisen. Für einige ist dies ein Vorteil, für jemanden ein Nachteil. Ich halte es für einen Vorteil, dass Sie die Funktion zur Berechnung der
bucket id
selbst auswählen können.
Was ist der Hauptunterschied zwischen klassischem Sharding und virtuellem Sharding mit Bucket?
Im ersten Fall, wenn wir die Zusammensetzung des Clusters ändern, haben wir zwei Zustände: den aktuellen (alten) und den neuen, in den wir gehen müssen. Während des Übergangsprozesses müssen Sie nicht nur die Daten übertragen, sondern auch die Hash-Funktionen für alle Datensätze neu berechnen. Dies ist sehr unpraktisch, da wir zu einem bestimmten Zeitpunkt nicht wissen, welche Daten bereits übertragen wurden und welche nicht. Darüber hinaus ist dies weder zuverlässig noch atomar, da für die atomare Übertragung eines Satzes von Datensätzen mit demselben Wert der Hash-Funktion der Übertragungsstatus dauerhaft gespeichert werden muss, falls eine Wiederherstellung erforderlich ist. Es gibt Konflikte, Fehler, Sie müssen die Prozedur viele Male neu starten.
Virtuelles Sharding ist viel einfacher. Wir haben nicht zwei ausgewählte Zustände des Clusters, wir haben nur den Zustand des Buckets. Der Cluster wird wendiger und bewegt sich allmählich von einem Zustand in einen anderen. Und jetzt gibt es mehr als zwei Staaten. Dank eines reibungslosen Übergangs können Sie das Guthaben im laufenden Betrieb ändern und den neu hinzugefügten Speicher löschen. Das heißt, die Steuerbarkeit des Auswuchtens wird stark erhöht, es wird granular.
Verwenden Sie
Angenommen, wir haben eine Funktion für die
bucket id
und so viele Daten in den Cluster eingegeben, dass kein Speicherplatz mehr vorhanden war. Jetzt möchten wir Knoten hinzufügen, damit die Daten selbst zu ihnen verschoben werden. In VShard geschieht dies wie folgt. Starten Sie zuerst neue Knoten und Tarantools und aktualisieren Sie dann die VShard-Konfiguration. Es beschreibt alle Clustermitglieder, alle Replikate, Replikatsätze, Master, zugewiesenen URIs und vieles mehr. Wir fügen der Konfiguration neue Knoten hinzu und verwenden sie mit der Funktion
VShard.storage.cfg
auf allen Knoten des Clusters.
function create_user(email) local customer_id = next_id() local bucket_id = crc32(customer_id) box.space.customer:insert(customer_id, email, bucket_id) end function add_account(customer_id) local id = next_id() local bucket_id = crc32(customer_id) box.space.account:insert(id, customer_id, 0, bucket_id) end
Wie Sie sich erinnern, ändert sich beim klassischen Sharding mit einer Änderung der Anzahl der Knoten auch die Shard-Funktion. In VShard passiert dies nicht, wir haben eine feste Anzahl von virtuellen Speichern - Bucket'ov. Dies ist die Konstante, die Sie beim Starten des Clusters auswählen. Aus diesem Grund scheint die Skalierbarkeit eingeschränkt zu sein, aber nicht wirklich. Sie können eine große Anzahl von Bucket'ov, Zehntausenden und Hunderttausenden auswählen. Die Hauptsache ist, dass mindestens zwei Größenordnungen mehr als die maximale Anzahl von Replikatsätzen vorhanden sein sollten, die Sie jemals im Cluster haben werden.

Da sich die Anzahl der virtuellen Speicher nicht ändert und die Shard-Funktion nur von diesem Wert abhängt, können wir so viele physische Speicher wie nötig hinzufügen, ohne die Shard-Funktion erneut anzugeben.
Wie werden Bukets selbst auf physische Geschäfte verteilt? Wenn VShard.storage.cfg auf einem der Knoten aufgerufen wird, wird der Neuausgleichsprozess aktiviert. Dies ist ein Analyseprozess, der das perfekte Gleichgewicht in einem Cluster berechnet. Er geht zu allen physischen Knoten, fragt, wer wie viele Bucket'ov hat, und erstellt Routen für ihre Bewegung, um die Verteilung zu mitteln. Der Rebalancer sendet Routen zu überfüllten Lagern, und sie beginnen, Eimer zu senden. Nach einiger Zeit wird der Cluster ausgeglichen.
In realen Projekten kann das Konzept der perfekten Balance jedoch anders sein. Ich möchte beispielsweise weniger Daten auf einem Replikatsatz als auf dem anderen speichern, da weniger Festplattenspeicher vorhanden ist. VShard glaubt, dass alles gut ausbalanciert ist, und tatsächlich ist mein Speicher kurz vor dem Überlaufen. Wir haben einen Mechanismus zum Anpassen der Ausgleichsregeln mithilfe von Gewichten bereitgestellt. Jeder Replikatsatz und jedes Repository kann gewichtet werden. Wenn der Balancer entscheidet, an wen er wie viele Eimer senden soll, berücksichtigt er die
Beziehung aller Gewichtspaare.
Zum Beispiel hat ein Geschäft ein Gewicht von 100 und das andere 200. Dann speichert das erste zweimal weniger Eimer als das zweite. Bitte beachten Sie, dass ich speziell über das Gewichtsverhältnis spreche. Absolute Bedeutungen haben keine Wirkung. Sie können Gewichte basierend auf einer 100% -Clusterverteilung auswählen: Ein Geschäft hat 30%, ein anderes 70%. Sie können die Speicherkapazität in Gigabyte als Basis verwenden oder die Gewichte in der Anzahl der Bucket'ov messen. Die Hauptsache ist, die Einstellung zu beobachten, die Sie brauchen.

Ein solches System hat einen interessanten Nebeneffekt: Wenn Sie einem Geschäft ein Gewicht von Null zuweisen, befiehlt der Balancer dem Geschäft, alle seine Eimer zu verteilen. Danach können Sie den gesamten Replikatsatz aus der Konfiguration entfernen.
Atomic Bucket Transfer
Wir haben einen Bucket, der Lese- und Schreibanforderungen akzeptiert, und dann fordert der Balancer auf, ihn in einen anderen Speicher zu übertragen. Bucket akzeptiert keine Aufzeichnungsanforderungen mehr, andernfalls können sie diese während der Übertragung aktualisieren. Dann haben sie Zeit, das tragbare Update, dann das tragbare Update-Update usw. auf unendlich zu aktualisieren. Daher ist der Datensatz blockiert und Sie können immer noch aus dem Bucket lesen. Die Übertragung von Brocken an einen neuen Ort beginnt. Nach Abschluss der Übertragung nimmt der Bucket erneut Anforderungen an. An der alten Stelle liegt es auch noch, aber es wurde bereits als Müll markiert und anschließend wird es vom Müllsammler Stück für Stück gelöscht.
Jeder Bucket ist Metadaten zugeordnet, die physisch auf der Festplatte gespeichert sind. Alle oben genannten Schritte werden auf der Festplatte gespeichert. Unabhängig davon, was mit dem Repository geschieht, wird der Status des Buckets automatisch wiederhergestellt.
Sie könnten Fragen haben:
- Was passiert mit den Anforderungen, die mit dem Bucket funktionierten, als sie mit dem Portieren begannen?
In den Metadaten jedes Buckets gibt es zwei Arten von Links: Lesen und Schreiben. Wenn der Benutzer eine Anfrage an den Bucket stellt, gibt er an, wie er damit arbeiten, schreibgeschützt oder schreibgeschützt schreiben wird. Für jede Anforderung wird der entsprechende Referenzzähler erhöht.
Warum brauche ich einen Referenzzähler zum Lesen von Anfragen? Angenommen, der Bucket wird leise übertragen, und hier kommt der Garbage Collector und möchte diesen Bucket löschen. Er sieht, dass die Anzahl der Links größer als Null ist, sodass Sie sie nicht löschen können. Und wenn die Anforderungen verarbeitet werden, kann der Garbage Collector seine Arbeit abschließen.
Der Referenzzähler zum Schreiben von Anforderungen stellt sicher, dass der Bucket nicht einmal zu übertragen beginnt, während mindestens eine Schreibanforderung damit arbeitet. Schreibanfragen können jedoch ständig eingehen, und dann wird der Eimer niemals übertragen. Tatsache ist, dass, wenn der Balancer den Wunsch geäußert hat, ihn zu übertragen, neue Aufzeichnungsanforderungen blockiert werden und das aktuelle System auf den Abschluss einer Zeitüberschreitung wartet. Wenn die Anforderungen nicht in der zugewiesenen Zeit abgeschlossen werden, akzeptiert das System erneut neue Schreibanforderungen und verschiebt die Übertragung des Buckets um einige Zeit. Somit unternimmt der Balancer die Übertragungsversuche, bis einer erfolgreich ist.
VShard verfügt über eine Bucket_Ref-API auf niedriger Ebene, falls Sie nur wenige Funktionen auf hoher Ebene haben. Wenn Sie wirklich etwas selbst tun möchten, greifen Sie einfach über den Code auf diese API zu. - Ist es möglich, Datensätze überhaupt nicht zu blockieren?
Es ist unmöglich. Wenn der Bucket wichtige Daten enthält, für die ein ständiger Schreibzugriff erforderlich ist, müssen Sie die Übertragung vollständig blockieren. bucket_pin
gibt es eine Funktion bucket_pin
, die den Bucket fest mit dem aktuellen Replikatsatz verbindet und dessen Übertragung verhindert. In diesem Fall kann sich der benachbarte Eimer ohne Einschränkungen bewegen.

Es gibt ein Tool, das noch leistungsfähiger ist als bucket_pin
- das Blockieren von Replikatsätzen. Dies geschieht nicht mehr im Code, sondern durch Konfiguration. Das Blockieren verbietet die Bewegung von Bucket'ov aus diesem Replikatset'a und den Empfang neuer. Dementsprechend stehen alle Daten ständig zur Aufzeichnung zur Verfügung.

VShard.router
VShard besteht aus zwei Submodulen: VShard.storage und VShard.router. Sie können selbst in einer Instanz unabhängig erstellt und skaliert werden. Beim Zugriff auf den Cluster wissen wir nicht, wo sich der Bucket befindet, und VShard.router sucht nach der
bucket id
für uns.
Schauen wir uns ein Beispiel an, wie das aussieht. Wir kehren zum Bankcluster und zu den Kundenkonten zurück. Ich möchte in der Lage sein, alle Konten eines bestimmten Clients aus dem Cluster zu ziehen. Dazu schreibe ich die übliche Funktion für die lokale Suche:

Sie sucht nach allen Kundenkonten anhand seiner ID. Jetzt muss ich entscheiden, welches der Repositorys diese Funktion aufrufen soll. Dazu berechne ich die
bucket id
aus der Client-ID in meiner Anfrage und fordere VShard.router auf, mir eine solche Funktion in dem Speicher aufzurufen, in dem der Bucket mit der resultierenden
bucket id
lebt. Im Submodul befindet sich eine Routing-Tabelle, in der die Position des Buckets im Replikatsatz angegeben ist. Und VShard.router vertritt meine Anfrage.
Natürlich kann es vorkommen, dass zu diesem Zeitpunkt das Resharding begann und sich der Eimer in Bewegung setzte. Der Router im Hintergrund aktualisiert die Tabelle schrittweise in großen Blöcken: Er fragt die Repositorys nach ihren aktuellen Bucket-Tabellen ab.
Es kann sogar vorkommen, dass wir uns dem gerade verschobenen Bucket zuwenden und der Router seine Routing-Tabelle noch nicht aktualisiert hat. Dann wendet er sich an das alte Repository und teilt dem Router entweder mit, wo er nach dem Bucket suchen soll, oder antwortet einfach, dass er nicht über die erforderlichen Daten verfügt. Dann durchsucht der Router alle Speicher auf der Suche nach dem gewünschten Bucket. Und das alles ist für uns transparent, wir werden nicht einmal einen Fehler in der Routing-Tabelle bemerken.
Instabilität lesen
Erinnern Sie sich daran, welche Probleme wir ursprünglich hatten:
- Es gab keine Datenlokalität. Wir haben uns entschieden, indem wir Bucket'ov hinzugefügt haben.
- Resharding verlangsamte alles und verlangsamte sich. Implementierte Atomic Data Transfer Bucket'ami, wurde das Nacherzählen von Shard-Funktionen beseitigt.
- Instabiles Lesen.
Das letzte Problem wird von VShard.router mithilfe des automatischen Lesefailover-Subsystems gelöst.
Der Router pingt regelmäßig den in der Konfiguration angegebenen Speicher an. Und dann hörten einige von ihnen auf zu pingen. Der Router verfügt über eine Hot-Backup-Verbindung zu jedem Replikat. Wenn das aktuelle Replikat nicht mehr reagiert, wird es zu einem anderen weitergeleitet. Die Leseanforderung wird normal verarbeitet, da wir Replikate lesen (aber nicht schreiben) können. Wir können die Priorität der Replikate festlegen, mit denen der Router das Failover für die Lesungen auswählen soll. Wir machen das mit Zoning.

Wir weisen jedem Replikat und jedem Router eine Zonennummer zu und legen eine Tabelle fest, in der wir den Abstand zwischen jedem Zonenpaar angeben. Wenn der Router entscheidet, wohin eine Leseanforderung gesendet werden soll, wählt er ein Replikat in der Zone aus, die seiner eigenen am nächsten liegt.
Wie es in der Konfiguration aussieht:

Im allgemeinen Fall können Sie auf ein beliebiges Replikat verweisen. Wenn der Cluster jedoch groß und komplex und sehr verteilt ist, ist das Zoning sehr nützlich. Verschiedene Server-Racks können Zonen sein, um das Netzwerk nicht mit Datenverkehr zu belasten. Oder es können Punkte sein, die geografisch voneinander entfernt sind.
Zoning hilft auch bei unterschiedlichen Replikationsleistungen. Zum Beispiel haben wir in jedem Replikatsatz ein Sicherungsreplikat, das keine Anforderungen akzeptieren sollte, sondern nur eine Kopie der Daten speichert. Dann schaffen wir es in der Zone, die sehr weit von allen Routern in der Tabelle entfernt ist, und sie werden sich im extremsten Fall daran wenden.
Instabilität der Aufnahme
Was ist mit dem Schreibfailover beim Ändern des Assistenten, da es sich um ein Lesefailover handelt? Hier ist VShard nicht so rosig: Die Wahl eines neuen Meisters ist darin nicht umgesetzt, Sie müssen es selbst tun. Wenn wir es irgendwie ausgewählt haben, ist es notwendig, dass diese Instanz jetzt die Autorität des Masters übernimmt. Wir aktualisieren die Konfiguration, indem wir
master = false
für den alten Master und
master = true
für den neuen angeben. Wenden Sie sie über VShard.storage.cfg an und rollen Sie sie in den Speicher. Dann passiert alles automatisch. Der alte Master akzeptiert keine Schreibanforderungen mehr und beginnt mit der Synchronisierung mit dem neuen Master, da möglicherweise bereits Daten auf den alten Master angewendet wurden, der neue jedoch noch nicht eingetroffen ist. Danach tritt der neue Master in die Rolle ein und beginnt, Anforderungen anzunehmen, und der alte Master wird zu einem Replikat. So funktioniert Write Failover in VShard.
replicas = new_cfg.sharding[uud].replicas replicas[old_master_uuid].master = false replicas[new_master_uuid].master = true vshard.storage.cfg(new_cfg)
Wie kann man nun all diese verschiedenen Ereignisse verfolgen?
Im Allgemeinen reichen zwei Handles aus -
VShard.storage.info
und
VShard.router.info
.
VShard.storage.info zeigt Informationen in mehreren Abschnitten an.
vshard.storage.info() --- - replicasets: <replicaset_2>: uuid: <replicaset_2> master: uri: storage@127.0.0.1:3303 <replicaset_1>: uuid: <replicaset_1> master: missing bucket: receiving: 0 active: 0 total: 0 garbage: 0 pinned: 0 sending: 0 status: 2 replication: status: slave Alerts: - ['MISSING_MASTER', 'Master is not configured for ''replicaset <replicaset_1>']
Der erste ist der Replikationsabschnitt. Der Status des Replikatsatzes, auf den Sie diese Funktion angewendet haben, wird angezeigt: Welche Replikationsverzögerung hat sie, mit wem hat sie Verbindungen und mit wem ist sie nicht verfügbar, wer ist verfügbar und nicht verfügbar, welcher Assistent ist für welche konfiguriert usw.
Im Abschnitt Bucket können Sie in Echtzeit sehen, wie viele Bucket'ov derzeit auf das aktuelle Replikatset verschoben werden, wie viele es verlassen, wie viele derzeit daran arbeiten, wie viele als Müll markiert sind und wie viele angehängt sind.
Der Alert-Bereich ist ein derartiges Durcheinander aller Probleme, die VShard unabhängig feststellen konnte: Der Master ist nicht konfiguriert, die Redundanzstufe ist unzureichend, der Master ist vorhanden und alle Replikate sind fehlgeschlagen usw.
Und der letzte Abschnitt ist ein Licht, das rot leuchtet, wenn es wirklich schlimm wird. Es ist eine Zahl von null bis drei, je mehr desto schlechter.
VShard.router.info hat die gleichen Abschnitte, aber sie bedeuten etwas anders.
vshard.router.info() --- - replicasets: <replicaset_2>: replica: &0 status: available uri: storage@127.0.0.1:3303 uuid: 1e02ae8a-afc0-4e91-ba34-843a356b8ed7 bucket: available_rw: 500 uuid: <replicaset_2> master: *0 <replicaset_1>: replica: &1 status: available uri: storage@127.0.0.1:3301 uuid: 8a274925-a26d-47fc-9e1b-af88ce939412 bucket: available_rw: 400 uuid: <replicaset_1> master: *1 bucket: unreachable: 0 available_ro: 800 unknown: 200 available_rw: 700 status: 1 alerts: - ['UNKNOWN_BUCKETS', '200 buckets are not discovered']
Der erste Abschnitt ist die Replikation. , : , replica set' , , , replica set' bucket' , .
Bucket bucket', ; bucket' ; , replica set'.
Alert, , , failover, bucket'.
, .
VShard?
— bucket'.
int32_max
? bucket' — 30 16 . bucket', . bucket', bucket'. , .
— -
bucket id
. , - , bucket — . , bucket' , VShard bucket'. -, bucket' bucket, -. .
Zusammenfassung
Vshard :
- ;
- ;
- ;
- read failover;
- bucket'.
VShard . - . —
. , . .
—
lock-free bucket' . , bucket' . , .
—
. : - , , ? .