Wie gestalte ich Datenspeicher für ein riesiges Tagging-System (wie digg oder delicious)?
Es gibt bereits Diskussion darüber, aber es ist über zentralisierte Datenbank. Da die Daten wachsen sollen, müssen wir die Daten bald oder später in mehrere Shards aufteilen. Die Frage lautet also: Wie wird der Datenspeicher für das partitionierte Tagging-System entworfen?
Das Tagging-System hat grundsätzlich 3 Tabellen:
%Vor%Das funktioniert einwandfrei, um alle Elemente für ein bestimmtes Tag zu finden und alle Tags für ein bestimmtes Element zu finden, wenn die Tabelle in einer Datenbankinstanz gespeichert ist. Wenn wir die Daten in mehrere Datenbankinstanzen aufteilen müssen, ist das nicht so einfach.
Für die Tabelle Item können wir den Inhalt mit dem Schlüssel item_id partitionieren. Für die Tabelle Tag können wir den Inhalt mit dem Schlüssel tag_id partitionieren. Zum Beispiel möchten wir die Tabelle Tag in K-Datenbanken partitionieren. Wir können einfach die Datenbank Nummer (tag_id% K) auswählen, um das angegebene Tag zu speichern.
Aber wie partitionieren Sie die Tabelle TagMapping ?
Die TagMapping -Tabelle repräsentiert die Viele-zu-Viele-Beziehung. Ich kann nur Bilder machen, um Duplikate zu haben. Das heißt, der gleiche Inhalt von TagMapping hat zwei Kopien. Einer ist mit tag_id partitioniert und der andere ist mit item_id partitioniert. In einem Szenario, in dem Tags für ein bestimmtes Element gefunden werden, verwenden wir eine Partition mit tag_id . Wenn im Szenario nach Elementen für ein bestimmtes Tag gesucht wird, verwenden wir die Partition mit Element-ID .
Als Ergebnis gibt es Datenredundanz. Und die Anwendungsebene sollte die Konsistenz aller Tabellen beibehalten. Es sieht schwer aus.
Gibt es eine bessere Lösung, um dieses Viele-zu-Viele-Partitionsproblem zu lösen?
Ich bezweifle, dass es einen einzigen Ansatz gibt, der alle möglichen Nutzungsszenarien optimiert. Wie Sie bereits gesagt haben, gibt es zwei Hauptszenarien, die die Tabelle TagMapping
unterstützt: Tags für ein bestimmtes Element suchen und Elemente mit einem bestimmten Tag finden. Ich denke, es gibt einige Unterschiede in der Verwendung der Tabelle TagMapping
für jedes Szenario, das von Interesse sein könnte. Ich kann nur vernünftige Annahmen basierend auf typischen Tagging-Anwendungen treffen, also verzeiht mir, wenn dies weit weg von der Basis ist!
Suchen von Tags für ein gegebenes Objekt
A1. Sie werden alle der Tags für ein bestimmtes Objekt auf einmal anzeigen
A2. Sie werden sicherstellen, dass all der Tags eines Elements eindeutig sind
Suchen nach Elementen für ein bestimmtes Tag
B1. Sie benötigen einige der Elemente für ein bestimmtes Tag (um eine Seite mit Suchergebnissen zu füllen)
B2. Sie könnten Benutzern erlauben, mehrere Tags anzugeben, sodass Sie einige der Elemente finden müssen, die mehreren Tags entsprechen
B3. Sie werden die Elemente für ein bestimmtes Tag (oder Tags) durch ein gewisses Maß an Popularität sortieren
Angesichts des oben Gesagten wäre es ein guter Ansatz, TagMapping
nach Element zu partitionieren. Auf diese Weise befinden sich alle Tags für ein bestimmtes Element auf einer Partition. Das Partitionieren kann granularer sein, da es wahrscheinlich weit mehr Elemente als Tags gibt und jedes Element nur eine Handvoll Tags hat. Dies erleichtert den Abruf (A1) und die Eindeutigkeit innerhalb einer einzelnen Partition (A2). Darüber hinaus kann diese einzelne Partition Ihnen sagen, ob ein Element mehreren Tags (B2) entspricht.
Da Sie nur einige der Elemente für ein bestimmtes Tag (oder mehrere Tags) gleichzeitig benötigen (B1), können Sie Partitionen nacheinander in einer bestimmten Reihenfolge abfragen, bis Sie so viele Datensätze haben benötigt, um eine Seite mit Ergebnissen zu füllen. Wie viele Partitionen Sie abfragen müssen, hängt davon ab, wie viele Partitionen Sie haben, wie viele Ergebnisse Sie anzeigen möchten und wie häufig das Tag verwendet wird. Jede Partition hätte einen eigenen Index für tag_id, um diese Abfrage effizient zu beantworten.
Die Reihenfolge, in der Sie Partitionen auswählen, ist wichtig, da sie die Gruppierung von Suchergebnissen beeinflusst. Wenn die Reihenfolge nicht wichtig ist (d. H. B3 spielt keine Rolle), wählen Sie die Partitionen nach dem Zufallsprinzip, damit keine Ihrer Partitionen zu heiß wird. Wenn die Reihenfolge wichtig ist, können Sie die Element-ID so konstruieren, dass sie Informationen codiert, die für die Reihenfolge relevant sind, in der die Ergebnisse sortiert werden sollen. Ein geeignetes Partitionierungsschema würde dann auf diese Codierung achten. Wenn es sich beispielsweise bei den Ergebnissen um URLs handelt, die nach Beliebtheit sortiert sind, können Sie eine sequenzielle Element-ID mit dem Google Page Rank-Wert für diese URL (oder etwas Ähnliches) kombinieren. Das Partitionierungsschema muss sicherstellen, dass alle Elemente in einer Partition die gleiche Punktzahl aufweisen. Abfragen würden Partitionen in der Reihenfolge auswählen, um sicherzustellen, dass populärere Elemente zuerst zurückgegeben werden (B3). Offensichtlich erlaubt dies nur eine Sortierart und die beteiligten Eigenschaften sollten konstant sein, da sie jetzt Teil eines Schlüssels sind und die Partition des Datensatzes bestimmen. Dies ist jedoch nicht wirklich eine neue Einschränkung, da es bei partitionierten Daten sowieso nicht einfach ist, verschiedene Arten zu unterstützen oder nach flüchtigen Eigenschaften zu sortieren.
Die Regel besteht darin, dass Sie nach dem Feld partitionieren, nach dem Sie abfragen wollen. Andernfalls müssen Sie alle Partitionen durchsuchen. Sind Sie sicher, dass Sie die Tag-Tabelle nur nach tag_id abfragen müssen? Ich glaube nicht, Sie müssen auch nach Titel Titel abfragen. Es ist nicht so offensichtlich für Item-Tabelle, aber wahrscheinlich möchten Sie auch durch etwas wie URL abfragen, um item_id dafür zu finden, wenn andere Benutzer Tags dafür zuweisen.
Beachten Sie jedoch, dass diese Tag- und Item-Tabellen unveränderlichen Titel und URL haben. Das bedeutet, dass Sie die folgende Technik verwenden können:
Sie verwenden entweder das Partitions-LocalID-Paar als globale Kennung oder verwenden nicht überlappende Nummernsets. Wie auch immer, jetzt können Sie Partition aus ID und Titel / URL Feldern berechnen. Sie kennen die Anzahl der Partitionen nicht im Voraus oder haben Bedenken, dass sich das in Zukunft ändern könnte? Erstelle mehr von ihnen und schließe dich Gruppen an, damit du sie in Zukunft neu gruppieren kannst.
Sicher, Sie können nicht dasselbe für die TagMapping-Tabelle tun, also müssen Sie duplizieren. Sie müssen es abfragen mit map_id, mit tag_id, mit item_id, oder? Auch ohne Partitionierung müssen Sie Daten duplizieren, indem Sie 3 Indizes erstellen. Der Unterschied besteht also darin, dass Sie für jeden Index eine andere Partitionierung (nach unterschiedlichem Feld) verwenden. Ich sehe keinen Grund, sich Sorgen zu machen.
Wahrscheinlich werden Ihre Abfragen mit einem Benutzer oder einem Thema zusammenhängen. Das bedeutet, dass Sie alle Informationen in Bezug auf diese an einem Ort haben sollten.
Sie sprechen über die Verteilung von DB, normalerweise ist dies meistens ein Problem der Synchronisation . Das Lesen, das normalerweise ungefähr 90% der Arbeit ausmacht, kann in einer replizierten Datenbank durchgeführt werden. Das Problem ist, wie man update eine DB und bleiben alle anderen konsistent und ohne die Leistungen zu töten. Dies hängt von Ihren Szenariodetails ab.
Die andere Möglichkeit besteht darin, wie Sie gefragt haben, alle Daten ohne Überlappung zu partitionieren. Sie würden wahrscheinlich nach Benutzer-ID oder Themen-ID partitionieren. Wenn Sie nach Themen-ID partitionieren, kann eine Datenbank auf alle Themen verweisen und nur mitteilen, welche dedizierte Datenbank die Daten enthält. Sie können dann das richtige abfragen. Da Sie nach ID partitionieren, können sich alle Informationen zu diesem Thema in dieser speziellen Datenbank befinden. Sie können auch nach Sprache oder nach Land für eine internationale Website partitionieren.
Zu guter Letzt werden Sie wahrscheinlich die beiden mischen: einige nicht überlappende Daten und einige überlappende (replizierte) Daten. Finden Sie zuerst die üblichen Operationen und dann finden Sie heraus, wie Sie diese in einer Datenbank mit möglichst wenig Abfragen erstellen können.
PS: Vergessen Sie nicht das Caching, es wird Sie mehr sparen als DB.
Tags und Links database partitioning tags tagging