Facebook Datenbank Design?

133

Ich habe mich immer gefragt, wie Facebook die <-> Benutzerbeziehung für Freunde gestaltet hat.

Ich denke, die Benutzertabelle ist ungefähr so:

user_email PK
user_id PK
password 

Ich bilde die Tabelle mit Benutzerdaten (Geschlecht, Alter usw., die per Benutzer-E-Mail verbunden sind, würde ich annehmen).

Wie verbindet es alle Freunde mit diesem Benutzer?

Etwas wie das?

user_id
friend_id_1
friend_id_2
friend_id_3
friend_id_N 

Wahrscheinlich nicht. Weil die Anzahl der Benutzer unbekannt ist und erweitert wird.

Marin
quelle
13
Es gibt eine Facebook-Engineering-Seite, die viele dieser Informationen enthält, aber nicht ganz das, was Sie fragen. Vielleicht möchten Sie dort fragen und sehen, ob Sie eine Antwort bekommen können. facebook.com/FacebookEngineering
John Meagher
1
Google graph database. Es ist sicher kein RDBMS.

Antworten:

90

Behalten Sie eine Freundes-Tabelle bei, die die Benutzer-ID und dann die Benutzer-ID des Freundes enthält (wir nennen sie Freund-ID). Beide Spalten wären Fremdschlüssel zurück zur Benutzertabelle.

Etwas nützliches Beispiel:

Table Name: User
Columns:
    UserID PK
    EmailAddress
    Password
    Gender
    DOB
    Location

TableName: Friends
Columns:
    UserID PK FK
    FriendID PK FK
    (This table features a composite primary key made up of the two foreign 
     keys, both pointing back to the user table. One ID will point to the
     logged in user, the other ID will point to the individual friend
     of that user)

Anwendungsbeispiel:

Table User
--------------
UserID EmailAddress Password Gender DOB      Location
------------------------------------------------------
1      bob@bob.com  bobbie   M      1/1/2009 New York City
2      jon@jon.com  jonathan M      2/2/2008 Los Angeles
3      joe@joe.com  joseph   M      1/2/2007 Pittsburgh

Table Friends
---------------
UserID FriendID
----------------
1      2
1      3
2      3

Dies wird zeigen, dass Bob sowohl mit Jon als auch mit Joe befreundet ist und dass Jon auch mit Joe befreundet ist. In diesem Beispiel wird davon ausgegangen, dass Freundschaft immer zwei Möglichkeiten hat, sodass Sie keine Zeile in der Tabelle wie (2,1) oder (3,2) benötigen, da diese bereits in der anderen Richtung dargestellt sind. In Beispielen, in denen Freundschaft oder andere Beziehungen nicht explizit wechselseitig sind, müssten diese Zeilen auch vorhanden sein, um die wechselseitige Beziehung anzugeben.

TheTXI
quelle
8
Denken Sie jedoch daran, wie ineffizient dies ist - Sie müssen eine disjunktive Abfrage für die Spalten der Viele-zu-Viele-Suche durchführen, wodurch sich die Suchzeit im Durchschnitt verdoppelt.
Anthony Bishopric
2
Persönlich möchte ich nicht, dass diese beiden Felder einen zusammengesetzten Primärschlüssel bilden. Ein einzigartiger Schlüssel, absolut. Der Clustered-Index für diesen eindeutigen Schlüssel auf jeden Fall. Aber ich würde auch eine Art nicht zusammengesetzte Identität als PK mit einem nicht gruppierten Index verwenden. Dies würde es anderen Tabellen ermöglichen, die eine "Freundschafts-ID" FK benötigen, sich leicht an diese Tabelle zu binden, und verschiedene Auslöser könnten ausgelöst werden, um Ereignisse von Freundschaften, Freundschaften usw. zu kaskadieren.
Jesse C. Slicer
1
Es heißt, dass Facebook rund 1'000'000'000 Nutzer hat. Wenn der durchschnittliche Benutzer 100 Freunde hat, bedeutet dies, dass die Tabelle 100'000'000'000 Zeilen enthält. MySQL-Partitionierung?
Veidelis
Vergiss diesen Ansatz. Wenn Sie eine ernsthafte Anzahl von Benutzern haben, wird es definitiv sehr langsam. Sehen Sie sich meine Antwort an und versuchen Sie, sie selbst zu bewerten. Ich habe ein Benchmarking mit 10.000 Benutzern und 2,5 Millionen Freundschaftsverbindungen durchgeführt und das Ergebnis war enttäuschend. Wenn Sie eine kleine Community betreiben, funktioniert dies einwandfrei, es sind jedoch Leistungsprobleme zu berücksichtigen.
Burzum
7
Sie können sicher sein, dass Facebook hierfür kein RDBMS verwendet. Es ist allgemein bekannt, dass sie, Twitter und alle anderen, die solche Abfragen ausführen müssen, eine Grafikdatenbank mit einem gewissen Geschmack verwenden. Es gibt mindestens 69 Leute, die noch nie auf irgendeiner Skala gearbeitet haben oder nicht wissen, wie man auf einer Skala rechnet.
51

Schauen Sie sich das folgende Datenbankschema an, das von Anatoly Lubarsky rückentwickelt wurde :

Facebook-Schema

Brad Larson
quelle
7
Dies ist ein Klassendiagramm, kein Datenbankschema
Zitronensaft
2
Hätte jeder "Benutzer" eine eigene Datenbank? Wie der oben? Wie würde es funktionieren? Beispiel: Wenn sich der Benutzer bei FB anmeldet, prüft er, ob es sich um einen gültigen User + Pass handelt, und leitet ihn dann zu seiner Datenbank um, die dann alles aus der obigen Datenbank
anzeigt
In diesem Shop werden nur die Informationen zum Benutzer gespeichert. Ich suche speziell nach dem Beitrag und seiner Zielgruppe.
Waseem Ahmad Naeem
47

TL; DR:

Sie verwenden eine Stapelarchitektur mit zwischengespeicherten Diagrammen für alles über dem MySQL-Boden ihres Stapels.

Lange Antwort:

Ich habe selbst einige Nachforschungen angestellt, weil ich neugierig war, wie sie mit ihrer riesigen Datenmenge umgehen und sie schnell durchsuchen. Ich habe Leute gesehen, die sich darüber beschwert haben, dass maßgeschneiderte Skripte für soziale Netzwerke langsam werden, wenn die Benutzerbasis wächst. Nachdem ich mich mit nur 10.000 Benutzern und 2,5 Millionen Freundverbindungen verglichen hatte - ohne mich um Gruppenberechtigungen, Likes und Pinnwandeinträge zu kümmern - stellte sich schnell heraus, dass dieser Ansatz fehlerhaft ist. Ich habe einige Zeit im Internet gesucht, um herauszufinden, wie ich es besser machen kann, und bin auf diesen offiziellen Facebook-Artikel gestoßen:

Ich empfehle Ihnen wirklich , sich die Präsentation des ersten Links oben anzuschauen, bevor Sie weiterlesen. Es ist wahrscheinlich die beste Erklärung dafür, wie FB hinter den Kulissen funktioniert.

Das Video und der Artikel erzählen ein paar Dinge:

  • Sie verwenden MySQL ganz unten in ihrem Stapel
  • Über der SQL-Datenbank befindet sich die TAO-Schicht, die mindestens zwei Caching-Ebenen enthält und zur Beschreibung der Verbindungen Diagramme verwendet.
  • Ich konnte nichts darüber finden, welche Software / Datenbank sie tatsächlich für ihre zwischengespeicherten Grafiken verwenden

Werfen wir einen Blick darauf, die Verbindungen zu Freunden sind oben links:

Geben Sie hier die Bildbeschreibung ein

Nun, das ist eine Grafik. :) Es sagt Ihnen nicht, wie Sie es in SQL erstellen sollen. Es gibt verschiedene Möglichkeiten, dies zu tun, aber diese Site bietet eine Reihe unterschiedlicher Ansätze. Achtung: Bedenken Sie, dass eine relationale Datenbank das ist, was sie ist: Es wird angenommen, dass normalisierte Daten gespeichert werden, keine Diagrammstruktur. Es funktioniert also nicht so gut wie eine spezialisierte Grafikdatenbank.

Denken Sie auch daran, dass Sie komplexere Abfragen durchführen müssen als nur Freunde von Freunden, beispielsweise wenn Sie alle Orte um eine bestimmte Koordinate filtern möchten, die Ihnen und Ihren Freunden von Freunden gefallen. Ein Diagramm ist hier die perfekte Lösung.

Ich kann Ihnen nicht sagen, wie Sie es so bauen sollen, dass es gut funktioniert, aber es erfordert eindeutig einige Versuche und Benchmarking.

Hier ist mein enttäuschender Test für nur Befunde Freunde von Freunden:

DB-Schema:

CREATE TABLE IF NOT EXISTS `friends` (
`id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `friend_id` int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

Freunde von Freunden Abfrage:

(
        select friend_id
        from friends
        where user_id = 1
    ) union (
        select distinct ff.friend_id
        from
            friends f
            join friends ff on ff.user_id = f.friend_id
        where f.user_id = 1
    )

Ich empfehle Ihnen wirklich, einige Beispieldaten mit mindestens 10.000 Benutzerdatensätzen zu erstellen, von denen jeder mindestens 250 Freundverbindungen hat, und diese Abfrage dann auszuführen. Auf meinem Computer (i7 4770k, SSD, 16 GB RAM) betrug das Ergebnis für diese Abfrage ~ 0,18 Sekunden . Vielleicht kann es optimiert werden, ich bin kein DB-Genie (Vorschläge sind willkommen). Doch wenn diese Skalen linear sind Sie bereits bei 1,8 Sekunden nur 100k Benutzer, 18 Sekunden für 1 Million Benutzer.

Dies mag für ~ 100.000 Benutzer immer noch in Ordnung klingen, aber denken Sie daran, dass Sie gerade Freunde von Freunden abgerufen haben und keine komplexeren Abfragen wie " Nur Beiträge von Freunden von Freunden anzeigen + Berechtigungsprüfung durchführen, ob ich erlaubt oder NICHT erlaubt bin" durchgeführt haben um einige von ihnen zu sehen + mache eine Unterabfrage, um zu überprüfen, ob mir einer von ihnen gefallen hat ". Sie möchten, dass die Datenbank überprüft, ob Ihnen ein Beitrag bereits gefallen hat oder nicht, oder ob Sie dies im Code tun müssen. Bedenken Sie auch, dass dies nicht die einzige Abfrage ist, die Sie ausführen, und dass Sie mehr als aktive Benutzer gleichzeitig auf einer mehr oder weniger beliebten Site haben.

Ich denke, meine Antwort beantwortet die Frage, wie Facebook die Beziehung seiner Freunde sehr gut gestaltet hat, aber es tut mir leid, dass ich Ihnen nicht sagen kann, wie Sie sie so implementieren können, dass sie schnell funktioniert. Die Implementierung eines sozialen Netzwerks ist einfach, aber es ist eindeutig nicht sicher, sicherzustellen, dass es gut funktioniert - IMHO.

Ich habe angefangen, mit OrientDB zu experimentieren, um die Diagrammabfragen durchzuführen und meine Kanten der zugrunde liegenden SQL-Datenbank zuzuordnen. Wenn ich es jemals schaffen sollte, werde ich einen Artikel darüber schreiben.

burzum
quelle
Also ... bist du jemals dazu gekommen, den Artikel zu schreiben?
FlowUI. SimpleUITesting.com
1
Nein, ich bin neben dem Programmieren ziemlich beschäftigt und hatte nicht die Zeit und Stimmung dazu. Die Antwort hier enthält alles, was Sie wissen müssen, wenn Sie performante Freundschaftszuordnungen implementieren möchten. Zwischenspeichern Sie entweder die Freundeslisten pro Benutzer oder ordnen Sie Ihre relationale Datenbank in Teilen oder im Ganzen einem Diagramm zu und fragen Sie die Diagramm-Datenbank ab. Sie können dafür OrientDB oder Neo4j verwenden. Ich würde gerne meine eigene Open-Source-Software für soziale Netzwerke schreiben, aber es gibt noch eine Menge anderer Dinge zu tun. Was auch immer Sie tun: Machen Sie Benchmarks. :)
burzum
Immer noch nein. In der OrientDB-Dokumentation werden jedoch die Verbindungen zu Freunden erläutert, und alles andere kann modelliert werden, sobald die Grundlagen verstanden sind. orientdb.com/docs/2.1/Tutorial-Working-with-graphs.html Wenn Sie eine relationale Datenbank als Grundlage verwenden möchten, müssen Sie nur Code in Ihre Rückrufe "nach dem Speichern" und "nach dem Löschen" einfügen, um Ihre Rückrufe zu aktualisieren Diagramm-DB (die Sie zum Lesen von Daten verwenden würden). Wenn Sie solche Rückrufe nicht haben, implementieren Sie sie, aber ich denke, fast alle Arten von ORM-Implementierungen und Frameworks haben so etwas. Tatsächlich kann OrientDB auch Dokumente speichern.
Burzum
1
Also ... bist du jemals dazu gekommen, den Artikel zu schreiben?
Connor Gurney
1
Immer noch nein, aber wir machen etwas Ähnliches bei der Arbeit: Wir ordnen unsere relationalen Daten einem Elastic Search-Index zu, wie ich in meinem Kommentar zuvor geschrieben habe. Es geht einfach darum, die Daten zu erhalten, die Sie nach einer bestimmten Aktion im Index oder Diagramm speichern möchten (Rückruf afterSave () / afterDelete () in unserem Fall) und anschließende Aktualisierung des Index oder der Grafik. Ziemlich einfach? :) Dasselbe könnte übrigens mit den Freundeslisten gemacht werden, es spielt keine Rolle, ob Sie sie in ES, einem Diagramm oder einem speicherbasierten Cache speichern (solange Sie über genügend RAM verfügen). Es ist wirklich nicht schwer, der schwierige Teil ist, das Ganze beim Wachsen skalieren zu lassen.
Burzum
32

Meine beste Wette ist, dass sie eine Diagrammstruktur erstellt haben . Die Knoten sind Benutzer und "Freundschaften" sind Kanten.

Behalten Sie eine Benutzertabelle, eine andere Kantentabelle. Dann können Sie Daten über die Kanten speichern, z. B. "Tag, an dem sie Freunde wurden" und "Genehmigter Status" usw.

belgariontheking
quelle
40
Ich habe das Gefühl, dass Sie das für einige Leute hier etwas mehr erklären müssen.
TheTXI
4
Ich denke, eine interessantere Frage wäre, wie eine so große Struktur (wir sprechen von 200 Millionen Knoten und Milliarden von Kanten) so beibehalten werden kann, dass sie leicht durchsucht und aktualisiert werden kann.
Dirk Vollmar
1
@divo: geschickte Verwendung von Indizes und Partitionen.
belgariontheking
20

Es ist höchstwahrscheinlich eine Beziehung von vielen zu vielen:

FriendList (Tabelle)

user_id -> users.user_id
friend_id -> users.user_id
friendVisibilityLevel

BEARBEITEN

Die Benutzertabelle hat user_email wahrscheinlich nicht als PK, möglicherweise jedoch als eindeutigen Schlüssel.

Benutzer (Tabelle)

user_id PK
user_email
password
Nathan Koop
quelle
4
Dies ist sicherlich am sinnvollsten, aber ich würde denken, dass die Leistung angesichts der Anzahl der Facebook-Nutzer und der Anzahl der Freunde, die jeder Facebook-Nutzer hat, schrecklich wäre.
Kevin Pang
17

Schauen Sie sich diese Artikel an, die beschreiben, wie LinkedIn und Digg aufgebaut sind:

Es gibt auch "Big Data: Standpunkte des Facebook-Datenteams", die hilfreich sein könnten:

http://developer.yahoo.net/blogs/theater/archives/2008/01/nextyahoonet_big_data_viewpoints_from_the_fac.html

Außerdem gibt es diesen Artikel, der sich mit nicht relationalen Datenbanken und deren Verwendung durch einige Unternehmen befasst:

http://www.readwriteweb.com/archives/is_the_relational_database_doomed.php

Sie werden sehen, dass diese Unternehmen mit Data Warehouses, partitionierten Datenbanken, Daten-Caching und anderen Konzepten auf höherer Ebene zu tun haben, mit denen sich die meisten von uns nie täglich befassen. Oder zumindest wissen wir vielleicht nicht, dass wir es tun.

Es gibt viele Links zu den ersten beiden Artikeln, die Ihnen mehr Einblick geben sollen.

UPDATE 20.10.2014

Murat Demirbas schrieb eine Zusammenfassung über

  • TAO: Facebooks verteilter Datenspeicher für den Social Graph (ATC'13)
  • F4: Facebooks warmes BLOB-Speichersystem (OSDI'14)

http://muratbuffalo.blogspot.com/2014/10/facebooks-software-architecture.html

HTH

Adrian J. Moreno
quelle
9

Es ist nicht möglich, Daten aus RDBMS für Benutzerfreunde abzurufen. Daten für Daten, die mehr als eine halbe Milliarde zu einem konstanten Zeitpunkt überschreiten. Facebook hat dies mithilfe einer Hash-Datenbank (kein SQL) implementiert und die Datenbank namens Cassandra geöffnet.

So hat jeder Benutzer seinen eigenen Schlüssel und die Details der Freunde in einer Warteschlange. Um zu wissen, wie Cassandra funktioniert, schauen Sie sich das an:

http://prasath.posterous.com/cassandra-55

user362541
quelle
Sehr interessant, danke mein Freund. Wann sind sie von SQL zu Cassandra gewechselt? weißt du zufällig?
Marin
1
Seien Sie sich bewusst: Posterous Spaces ist tot ... also der Link.
TechNyquist
5

Sie suchen nach Fremdschlüsseln. Grundsätzlich können Sie kein Array in einer Datenbank haben, es sei denn, es hat eine eigene Tabelle.


Beispielschema:

    Benutzertabelle
        Benutzer-ID PK
        andere Daten
    Freundes Tisch
        userID - FK zur Benutzertabelle, die den Benutzer darstellt, der einen Freund hat.
        friendID - FK zur Benutzertabelle, die die Benutzer-ID des Freundes darstellt
Malfist
quelle
5
Warum die Abstimmungen? Lassen Sie zumindest jemanden wissen, warum Sie ihn herabgestimmt haben.
Sasha Chedygov
3
@freak: Warum? Das gesamte Konzept der Abstimmung auf dieser Website sieht vor, dass die Abstimmung anonym ist. Warum hat Malfist Ihrer Meinung nach Anspruch auf irgendetwas?
GEOCHET
4
Besonders wenn es eine gültige Antwort ist und von den anderen Antworten wiederholt wird (obwohl ich nicht von ihnen kopiert habe, als ich antwortete, gab es dort keine Antworten)
Malfist
4
@TheTXI: Ich denke, Kommentare zu Abstimmungen sind eine Höflichkeit, insbesondere zu Antworten, die sie offensichtlich nicht verdienen, aber ich stimme auch zu, dass Kommentare nicht vorgeschrieben werden sollten.
Robert S.
2
Personen, die anonym über nicht offensichtliche Antworten abstimmen, befürchten, dass ihre oberflächliche Argumentation entlarvt wird, wenn sie einen Kommentar hinterlassen, der eine Ablehnung erklärt.
Vinayak
1

Beachten Sie, dass Datenbanktabellen so konzipiert sind, dass sie vertikal (mehr Zeilen) und nicht horizontal (mehr Spalten) wachsen.

Neil N.
quelle
24
NIE VERGESSEN! Mein Vater starb, weil ein DB-Tisch für seine Spalten zu weit vertikal gewachsen war. Ich werde dich vermissen, Dad.
belgariontheking
1
hmm, warum das downvote? Und der Kommentar darüber macht keinen Sinn.
Neil N
2
Nein, der Kommentar macht keinen Sinn. Scheint, als hätte jemand versucht, lustig zu sein, also macht es nichts aus.
Dirk Vollmar
0

In Bezug auf die Leistung einer Viele-zu-Viele-Tabelle beträgt Ihr grundlegender Datenspeicher für 200.000.000 Benutzer mit durchschnittlich 200 Freunden pro Stück knapp 300 GB, wenn Sie über 2 32-Bit-Ints verfügen, die Benutzer-IDs verknüpfen.

Offensichtlich würden Sie eine Partitionierung und Indizierung benötigen, und Sie werden dies nicht für alle Benutzer im Speicher behalten.

Cade Roux
quelle
0

Wahrscheinlich gibt es eine Tabelle, in der die <-> Benutzerbeziehung des Freundes gespeichert ist, z. B. "frnd_list", mit den Feldern 'user_id', 'frnd_id'.

Immer wenn ein Benutzer einen anderen Benutzer als Freund hinzufügt, werden zwei neue Zeilen erstellt.

Angenommen, meine ID lautet 'deep9c' und ich füge einen Benutzer mit der ID 'akash3b' als Freund hinzu. Dann werden in der Tabelle "frnd_list" zwei neue Zeilen mit den Werten ('deep9c', 'akash3b') und ('akash3b' erstellt ',' deep9c ').

Wenn Sie nun die Freundesliste einem bestimmten Benutzer anzeigen, würde ein einfaches SQL Folgendes tun: "Wählen Sie frnd_id aus frnd_list aus, wobei user_id =" wobei die ID des angemeldeten Benutzers ist (als Sitzungsattribut gespeichert).

deep9c
quelle