Durchsuchen von Shards?

8

Kurzversion

Wenn ich meine Benutzer in Shards aufteile, wie biete ich eine "Benutzersuche" an? Offensichtlich möchte ich nicht, dass jede Suche jeden Splitter trifft.

Lange Version

Mit Shard habe ich mehrere Datenbanken, von denen jede einen Bruchteil der gesamten Daten enthält. Für ein naives Beispiel können die Datenbanken UserA, UserB usw. Benutzer enthalten, deren Namen mit "A", "B" usw. beginnen. Wenn sich ein neuer Benutzer anmeldet, prüfe ich einfach seinen Namen und setze ihn in die richtige Richtung Datenbank. Wenn sich ein wiederkehrender Benutzer anmeldet, schaue ich erneut auf seinen Namen, um die richtige Datenbank zu ermitteln, aus der er seine Informationen abrufen kann.

Der Vorteil von sharded vs read replication besteht darin, dass die read replication Ihre Schreibvorgänge nicht skaliert. Alle Schreibvorgänge, die zum Master gehen, müssen zu jedem Slave gehen. In gewisser Weise tragen sie alle dieselbe Schreiblast, obwohl die Lese-Last verteilt ist.

Währenddessen interessieren sich Scherben nicht für die Schreibweisen der anderen. Wenn sich Brian beim UserB-Shard anmeldet, muss der UserA-Shard nichts davon hören. Wenn Brian eine Nachricht an Alex sendet, kann ich diese Tatsache sowohl in den UserA- als auch in den UserB-Shards aufzeichnen. Wenn sich entweder Alex oder Brian einloggen, kann er alle seine gesendeten und empfangenen Nachrichten von seinem eigenen Shard abrufen, ohne alle Shards abzufragen.

So weit, so gut. Was ist mit Suchen? Wenn Brian in diesem Beispiel nach "Alex" sucht, kann ich UserA überprüfen. Aber was, wenn er nach Alex mit seinem Nachnamen "Smith" sucht? Es gibt Smiths in jeder Scherbe. Von hier aus sehe ich zwei Optionen:

  1. Lassen Sie die Anwendung in jedem Shard nach Smiths suchen. Dies kann langsam erfolgen (Abfragen jedes Shards nacheinander) oder schnell (paralleles Abfragen jedes Shards), aber jeder Shard muss in jede Suche einbezogen werden. Auf dieselbe Weise wie die Lesereplikation keine Schreibvorgänge skaliert, werden Ihre Suchvorgänge nicht skaliert, wenn Suchvorgänge auf alle Fragmente angewendet werden. Du kannst einen Zeitpunkt erreichen, an dem dein Suchvolumen hoch genug ist, um jeden Shard zu überwältigen, und das Hinzufügen von Shards hilft dir nicht, da sie alle das gleiche Volumen haben.
  2. Eine Art von Indizierung, die selbst Sharding toleriert. Nehmen wir zum Beispiel an, dass ich eine konstante Anzahl von Feldern habe, nach denen ich suchen möchte: Vorname und Nachname. Zusätzlich zu UserA, UserB usw. habe ich auch IndexA, IndexB usw. Wenn sich ein neuer Benutzer anmeldet, füge ich ihn an jeden Index an, auf dem er gefunden werden soll. Also habe ich Alex Smith sowohl in IndexA als auch in IndexS platziert, und er kann entweder auf "Alex" oder "Smith" gefunden werden, aber keine Teilstrings. Auf diese Weise müssen Sie nicht jeden Shard abfragen, daher kann die Suche skalierbar sein.

Kann also die Suche skaliert werden? Wenn ja, ist dieser Indexierungsansatz der richtige? Gibt es noch andere?

    
Gintautas Miliauskas 04.11.2008, 00:06
quelle

5 Antworten

7

Es gibt kein Wundermittel.

Die Suche nach jedem Shard in Folge ist natürlich aufgrund der unglaublich hohen Latenz nicht möglich.

Sie wollen also parallel suchen, wenn Sie müssen.

Es gibt zwei realistische Optionen, die Sie bereits aufgelistet haben: Indizierung und parallelisierte Suche. Erlauben Sie mir, näher darauf einzugehen, wie Sie sie gestalten würden.

Die wichtigste Erkenntnis, die Sie verwenden können, ist, dass Sie in der Suche selten den vollständigen Satz von Ergebnissen benötigen. Sie brauchen nur die erste (oder n-te) Seite der Ergebnisse. Es gibt also ziemlich viel Spielraum, um die Reaktionszeit zu verkürzen.

Indizierung

Wenn Sie die Attribute kennen, nach denen die Benutzer gesucht werden, können Sie benutzerdefinierte, separate Indizes für sie erstellen. Sie können Ihren eigenen invertierten Index erstellen, der auf das Tupel (shard, recordId) für jeden Suchbegriff oder auf Sie verweist kann es in der Datenbank speichern. Aktualisieren Sie es langsam und asynchron. Ich kenne Ihre Anwendungsanforderungen nicht, es könnte sogar möglich sein, den Index jede Nacht neu zu erstellen (was bedeutet, dass Sie an einem bestimmten Tag nicht die neuesten Einträge haben - aber das könnte für Sie in Ordnung sein). Stellen Sie sicher, dass dieser Index für die Größe optimiert wird, damit er in den Speicher passt. Beachten Sie, dass Sie diesen Index bei Bedarf überschreiben können.

Wenn Leute nach etwas wie "lastname='Smith' OR lastname='Jones'" suchen können, können Sie natürlich den Index für Smith lesen, den Index für Jones lesen und die Union berechnen - Sie müssen nicht alle möglichen Abfragen speichern, nur ihre Gebäudeteile .

Parallele Suche

Senden Sie für jede Abfrage Anforderungen an alle Shards, sofern Sie nicht wissen, nach welchem ​​Shard gesucht werden soll, da sich die Suche zufällig auf dem Verteilungsschlüssel befindet. Machen Sie die Anfragen asynchron. Antworten Sie dem Benutzer, sobald Sie die erste Seite der Ergebnisse erhalten; Sammeln Sie den Rest und cachen Sie lokal, so dass, wenn der Benutzer auf "Weiter" klickt, Sie die Ergebnisse bereit haben und die Server nicht erneut abfragen müssen. Wenn einige der Server länger dauern als andere, müssen Sie nicht darauf warten, dass die Server die Anfrage bearbeiten.

Wenn Sie schon dabei sind, protokollieren Sie die Antwortzeiten der Server, die sich im Sharded-Modus befinden, um mögliche Probleme mit ungleichmäßigen Daten und / oder Lastverteilung zu erkennen.

    
SquareCog 06.11.2008 02:20
quelle
2

Ich gehe davon aus, dass Sie über Scherben sprechen: Ссылка

Wenn Sie diesen Artikel lesen, geht er genau auf Ihre Frage ein, aber lange Antwort kurz, Sie schreiben benutzerdefinierten Anwendungscode, um Ihre unterschiedlichen Splitter zusammen zu bringen. Sie können Smart Hashing durchführen, um einzelne Shards abzufragen und Daten in Shards einzufügen. Sie müssen eine spezifischere Frage stellen, um eine spezifischere Antwort zu erhalten.

    
Zak 04.11.2008 00:32
quelle
1

Sie brauchen tatsächlich jede Suche, um jeden Shard zu treffen, oder zumindest muss jede Suche nach einem Index durchgeführt werden, der die Daten von allen Shards enthält, was auf dasselbe hinausläuft.

Vermutlich basiert das Shard auf einer einzigen Eigenschaft des Benutzers, wahrscheinlich auf einem Hash des Benutzernamens. Wenn Ihre Suchfunktion dem Benutzer ermöglicht, basierend auf anderen Eigenschaften des Benutzers zu suchen, ist klar, dass es keinen einzelnen Shard oder eine Teilmenge von Shards gibt, die eine Abfrage erfüllen können, da ein Shard Benutzer enthalten kann, die der Abfrage entsprechen. Sie können keine Shards vor der Suche ausschließen, was bedeutet, dass Sie die Abfrage für alle Shards ausführen müssen.

    
user33830 04.11.2008 00:37
quelle
1

Sie können sich Sphinx ( Ссылка ) ansehen. Es unterstützt die verteilte Suche. GigaSpaces hat eine parallele Abfrage- und Zusammenführungsunterstützung. Dies kann auch mit MySQL Proxy ( Ссылка ) erfolgen.

Um eine nicht-sharded indizierte Arten zu erstellen, wird der Zweck des Shards an erster Stelle besiegt :-) Ein zentralisierter Index wird wahrscheinlich nicht funktionieren, wenn Shards notwendig sind.

Ich denke, alle Scherben müssen parallel getroffen werden. Die Ergebnisse müssen gefiltert, sortiert, sortiert, gruppiert und die Ergebnisse aus allen Shards zusammengeführt werden. Wenn die Scherben selbst überwältigt werden, musst du das übliche tun (Reshard, Scale Up, etc.), um sie wieder zu überwältigen.

    
Todd Hoff 06.11.2008 20:42
quelle
0

RDBMs sind kein gutes Werkzeug für die Textsuche. Sie werden viel besser auf Solr schauen. Der Leistungsunterschied zwischen Solr und der Datenbank wird in der Größenordnung von 100X liegen.

    
jeff musk 11.02.2012 01:40
quelle

Tags und Links