Gewusst wie-Seiten wie LinkedIn effizient display 1st/2nd/3rd-level-Beziehung neben jeder person den Namen?
Ich vor kurzem verkorksten Vorstellungsgespräch schlecht beantworten eine einfache Frage: wie kann Seiten wie LinkedIn effizient zeigen die Beziehung Distanz (1./2./3.) von Ihnen jede person, die auf einer Seite angezeigt (z.B. in Personen-Suche Ergebnisse, die Liste der Leute in einer Firma arbeitet, etc.)?
<EDIT> ich bekam den wesentlichen "trick" die Lösung: Suche nach "Abstand von mir" ist eine gemeinsame operation (z.B. 20x+ auf einer einzigen Seite, 100 pro login-session), so kann ein Teil der "Abstand von mir zu X", Zwischenspeichern, und dann wieder verwenden, die Cache Teilergebnis viele Male in Reihenfolge zu make andere Operationen viel billiger. Ich vermutete auch, dass die teilweise Ergebnis war wahrscheinlich meine zweite-Ebene-verbindungen, weil "cache alle 3rd-level-verbindungen" wäre zu teuer in RAM und CPU.</EDIT>
Aber wenn Sie versuchen zu konvertieren, das Einblick in eine Lösung, ich kam mit einem stümperhaften Antwort mit erstellen von persistenten caches 2nd-level-verbindungen von jedem auf der Website (die hätte enorm epensive im perf und Komplex zu halten), und ich nahm einen unerklärlichen Umweg in Bloom-Filter in einer Weise, die wenig technischen Sinn. Ich würde nicht gemietet haben, selbst nach einer Antwort wie, die!
Später, als ich dachte über das problem, ohne den Druck des Vorstellungsgesprächs hängt über meinem Kopf, kam ich auf eine vernünftige Antwort.
-
Bauen ein sehr schneller Weg, um die erste Ebene der verbindungen für jede charge von Benutzer-IDs (batch-Größe von bis zu ~1000?). Dies bedeutet wahrscheinlich eine dedizierte cluster von lose-von-RAM-Server, die in den cache-Speicher das gesamte Netzwerk der 1st-level-verbindungen im Speicher. Zum Glück, 50M-Mitglieder x avg. 100 verbindungen pro Mitglied x 4 Byte pro Element-ID = <25 GB an cache im RAM, das ist machbar mit preiswerten hardware. Und die Anzahl der änderungen pro Tag zu unter 1%, so halten Sie die cache-up-to-date ist nicht allzu schwer. (Beachten Sie, dass eine relationale Datenbank wäre wohl eine schlechte Wahl zu implementieren, die diesen cache, weil die "viel random I/O" Zugriff Muster tötet relationalen DB-Leistung.)
-
wenn sich ein Benutzer anmeldet, cache seine 2nd-level-verbindungen durch das Holen von 1st-level-verbindungen von jedem 1st-level-verbindungen, und den stick in eine hashtable (key = 2nd-level-ID, Wert = array mit 1st-level-verbindungen, die verbinden Sie). Auch cache der first-level-verbindungen zu, so können Sie sich zurück ziehen beide 1st - und 2nd-level über einen einzigen Anruf wieder zu Ihrem remote-cache-server. Benutzer-IDs sind leicht teilbaren, also eine verteilte Caches wie memcached kann funktionieren gut für diese.
-
für jede Benutzer-ID, zu finden, ob es in Ihrem "Netzwerk" und in welcher Beziehung er zu Ihnen (1., 2., 3.), tun Sie den folgenden:
- wenn die ID in Ihrem first-level-verbindungen, stop.
- versuchen, suchen Sie die ID in Ihrem Cache 2nd-level-verbindungen hashtable. Wenn gefunden, gib den array von verbindungen, die verbinden.
- holt den ID der ersten Ebene-verbindungen, und wiederholen Sie Schritt 2 für jeden von Ihnen. Zusammenfassen aller Ergebnisse in einem einzigen array und gibt Sie zurück.
- <EDIT> umgestalten in eine batch-Umsetzung ("look-up-Entfernung von mir bis zu N verschiedene Nutzer"), so können Sie die remote-Ergebnisse von Schritt #3 die zimmerreserviereung, ohne das make up zu N remote-Aufrufe.</EDIT>
Aber ich bin sicher, es gibt bessere Antworten auf diese. Was ist deins? Wenn Sie möchten, dass zusätzliche Herausforderung, versuchen Sie die Simulation ein inteview situation (can ' T look up-Lösungen auf dem Web).
Beachten Sie, dass die Frage war über eine optimale Lösung, unabhängig von wie LinkedIn tatsächlich tut Sie es heute, die ich sah, nachdem ich schrieb meine Antwort oben.
- Ich hoffe, dass Sie die Anwendung wurden bei LinkedIn oder Ihre Mitbewerber (oder einem Ort verwenden möchte, dass die Technik für etwas). Wenn nicht, klingt wie der interviewer wusste nicht wirklich, was er oder Sie tut---was schade ist.
- Yep, effiziente Analysen von sozialen Netzwerken war ein wichtiger Teil dieses Unternehmens, so dass diese Frage hatte praktische Relevanz. Plus ich denke, es ist eine vernünftige Allgemeinen test anwenden zu können, theoretische informatik-Ideen in einem realen Umfeld, wo Dinge wie RAM vs. I/O-Geschwindigkeit, hardware-Kosten vs. Programmierer Aufwand, und die lokale vs. remote-Platzierung von code sehr wichtig. Der Nachteil, natürlich, ist, herauszufinden, eine gute Lösung (wenn Sie nicht bereits vertraut mit dem problem) habe ich mehr als 5 Minuten!
- "Ich würde nicht gemietet haben, selbst nach einer Antwort und so!" - Dort gewesen, getan, dass
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie in der Lage, zu nutzen, die Axiome über kleine-Welt-Netzwerke optimieren diese Art der Traversierung.
Kleine-Welt-Netzwerke sind gekennzeichnet durch die "hubs" (das sind sehr Dichte verbindungen von anderen Knoten. Die meisten Knoten im Netzwerk wird in der Regel entweder die Verbindung innerhalb von ein paar Hopfen zu einem topologisch nahen Knoten (1-4 hops entfernt), oder wird die route über eine oder mehrere solcher hubs. Dies ist einer der Hauptgründe, dass die kleine-Welt-Netzwerke Verhalten, wie Sie es tun.
Interessanterweise 1970 die Technologie würde einen fairen job der Modellierung dieser. Die Netzwerk-Datenbank-Modell effizient verwaltet diese Art von Beziehung.
Es ist nicht effizient im Hinblick auf ad-hoc-Abfragen oder Daten-Modell Pflege, so Ungnade fiel mit dem Aufstieg der relationalen Datenmodellen.
Wenn Sie darüber nachdenken, tun dies in SQL könnte sehr Prozessor intensiv.
Gegeben, dass und die Tatsache, dass es letztendlich werden alle über dem Platz, und dieser Raum ist relativ Billig...ich würde empfehlen die Erstellung eines Indexes mit Hilfe von Lucene (oder Lucene.NET) je nach der Sprache. Könnten Sie tun, ein paar Dinge anders.
Können Sie entweder eine Art von Struktur Daten Struktur und rekursiv durchforsten Sie Ihre index-Suche für alle übergeordneten Knoten oder untergeordneten Knoten und deren Eltern-oder Kind-Knoten je nach Ihren Bedürfnissen zu der Zeit.
Oder Sie können schreiben, alle Beziehungen, wie Sie erstellt werden (der Raum ist Billig-Konzept). Dies wäre ein " write once-Verfahren (, die Sie nicht updaten, alle, die oft beliebige Art und Weise). Wenn eine Beziehung geschaffen ist oder widerrufen würden Sie Warteschlange ein update zu Ihrem index (Warteschlange, weil Sie würde nicht wollen, zu öffnen für den Schreibzugriff für einzelne Aufträge...die batch-index-updates). Dann könnten Sie Lesen, dieses wirklich flache Struktur, um die IDs in Frage.
Mit den IDs in der hand (von denen immer suchen, geben Sie ausführen) kannst du dann gehen, um die DB zu bekommen die Umgebung erforderlichen Informationen ein. Dann cache der Ausgabe weiter zu minimieren, was wäre eine sehr schnelle Suche, db-Abfrage, Daten, Gebäude...aber noch schneller, wenn es kommt aus dem cache.
Etwas wie Velocity, MemCached, oder MemCached-Win32 für Ihre zentrale Zwischenspeicherung über eine web-farm.
Ich nicht sicher bin ob die Struktur der Tabelle oder die Komplexität des Systems, aber hier ist eine einfache SQL-Server-Beispiel mit einer rekursiven CTE:
AUSGABE:
Umzusetzen
Verwenden Tatsache, die verbindungen sind bidirektional.
Store 1st-level-verbindungen als sortierte Liste in einigen KV wund:
Pseudocode:
Komplexität: O(C1+C2). C1,C2 - Anzahl der Verbindung der beiden Benutzer.
Ist nicht linkedin-Daten, dargestellt als ein riesiger graph? und wenn eine person Anmeldungen, das system würde ein handle zu seiner Knoten, und dann tut breadth first traversal für 3 Ebenen, das system halten würde, diese Knoten als set(zusammen mit dem level info), und wenn eine person erscheint auf der Webseite, das system führt eine Suche auf diesen Knoten gesetzt und gibt das Verhältnis der Entfernung..
Dies ist meine Vermutung. Bitte fühlen Sie sich frei zu zeigen, was es unpraktisch.