it-swarm.dev

Was ist der beste Weg, um eine Website so zu gestalten, dass sie hoch skalierbar ist?

Wie lässt sich die Website am besten gestalten, wenn Websites hochskalierbar sein müssen, z. B. soziale Netzwerke wie Facebook?

  1. Sollte ich einen Webdienst haben, den die Site abfragt, um die benötigten Daten abzurufen?

    oder

  2. Sollte die Site Datenbanken direkt abfragen? (kann mit eingebauten Sprachkonstrukten durchgeführt werden, um Tabellen automatisch zu füllen usw.).

Ich würde denken, dass der Webdienst das bessere Design ist, da er einen zentralisierten Datenzugriff ermöglicht und Dinge wie Caching und dergleichen viel einfacher zu steuern sind. Aber was denken andere?

37
Daniel

Wow, das ist eine einfache Frage, die eine Vielzahl möglicher Antworten bietet. Der explizitere Teil Ihrer Frage fragt, ob es skalierbarer ist, direkt oder über einen Webdienst mit Ihrer Datenbank zu kommunizieren. Diese Antwort ist einfach: Fragen Sie die Datenbank direkt ab. Durch das Durchlaufen des Webdienstes wird eine ganze Reihe von Latenzen hinzugefügt, die für Code, der hinter einer Firewall (im Großen und Ganzen) ausgeführt wird, völlig unnötig sind. Ein Webdienst erfordert beispielsweise, dass eine Komponente eine Anforderung empfängt, deserialisiert, die Datenbank abfragt, eine Antwort serialisiert und zurückgibt. Wenn Ihr Code also alle hinter einer Firewall ausgeführt wird, sparen Sie sich die Mühe und fragen Sie einfach die Datenbank direkt ab.

Die Skalierbarkeit einer Website geht jedoch weit über die ursprünglich gestellte Frage hinaus. Verzeihen Sie mir also, wenn ich hier auf eine Tangente gehe, aber ich dachte, es könnte nützlich sein, wenn man bedenkt, dass Sie insbesondere Facebook erwähnt haben.

Ich würde Ihnen empfehlen, sich über die Arbeit und Tools von Brad Fitzpatrick (Gründer von LiveJournal und jetzt bei Google) zu informieren. Als ich bei Six Apart mit ihm zusammengearbeitet habe, habe ich einige Dinge von ihm gelernt und die Architektur von LiveJournal, die es so skalierbar gemacht hat.

  1. Verwenden Sie schmale Datenbanktabellen im Gegensatz zu breiten. Das Faszinierende daran war zu lernen, was diese Architektur motivierte, die ein System schuf, das einfach und schnell aktualisiert werden konnte. Wenn Sie breite Tabellen oder Tabellen verwenden, für die jedes Feld oder jede Eigenschaft eine Spalte in der Tabelle ist, muss das System beim Aktualisieren des Datenbankschemas, z. B. Hinzufügen einer neuen Spalte, die Tabelle während des Schemas sperren Änderung wird implementiert. Wenn Sie im Maßstab arbeiten, bedeutet dies, dass eine einfache Änderung des Datenbankschemas zu einem großen Datenbankausfall führen kann. Was offensichtlich scheiße ist. Eine schmale Tabelle hingegen speichert einfach jede einzelne Eigenschaft, die einem Objekt zugeordnet ist, als einzelne Zeile in der Datenbank. Wenn Sie der Datenbank eine neue Spalte hinzufügen möchten, müssen Sie daher nur Datensätze in eine Tabelle einfügen, was nicht sperrend ist. Ok, das ist ein kleiner Hintergrund. Mal sehen, wie sich dieses Modell tatsächlich in ein funktionierendes System wie LiveJournal übersetzt.

    Angenommen, Sie möchten die letzten 10 Journaleinträge in das Blog einer Person laden, und jeder Journaleintrag verfügt über zehn Eigenschaften. In einem klassischen Layout für breite Tabellen würde jede Eigenschaft mit einer Spalte in einer Tabelle korrelieren. Ein Benutzer würde dann die Tabelle einmal abfragen, um alle benötigten Daten abzurufen. Die Abfrage würde 10 Zeilen zurückgeben und jede Zeile würde alle Daten enthalten, die sie benötigen (z. B. SELECT * FROM-Einträge ORDER BY date LIMIT 10). In einem engen Tabellenlayout sieht es jedoch etwas anders aus. In diesem Beispiel gibt es tatsächlich zwei Tabellen: Die erste Tabelle (Tabelle A) speichert einfache Kriterien, nach denen gesucht werden soll, z. die ID des Eintrags, die ID des Autors, das Datum des Eintrags usw. In einer zweiten Tabelle (Tabelle B) werden dann alle mit einem Eintrag verknüpften Eigenschaften gespeichert. Diese zweite Tabelle enthält drei Spalten: entry_id, key und value. Für jede Zeile in Tabelle A gibt es 10 Zeilen in Tabelle B (eine Zeile für jede Eigenschaft). Um die letzten zehn Einträge abzurufen und anzuzeigen, benötigen Sie daher 11 Abfragen. Die erste Abfrage gibt Ihnen die Liste der Eintrags-IDs, und die nächsten zehn Abfragen rufen die Eigenschaften ab, die jedem der in der ersten Abfrage zurückgegebenen Einträge zugeordnet sind.

    "Heiliger Moly!" Sie sagen: "Wie um alles in der Welt kann das skalierbarer sein?!" Es ist völlig kontraintuitiv, oder? Im ersten Szenario hatten wir nur eine Datenbankabfrage, aber in der zweiten "skalierbareren" Lösung haben wir 11 Datenbankabfragen. Das macht keinen Sinn. Die Antwort auf diese Frage hängt ganz von der nächsten Kugel ab.

  2. Verwenden Sie Memcache großzügig. Falls Sie sich nicht bewusst waren, ist Memcache ein verteiltes, zustandsloses, netzwerkbasiertes Caching-System mit geringer Latenz. Es wird von Facebook, Google, Yahoo und nahezu jeder beliebten und skalierbaren Website der Welt verwendet. Es wurde von Brad Fitzpatrick teilweise erfunden, um den Datenbankaufwand auszugleichen, der einem Datenbankdesign mit engen Tabellen inhärent ist. Schauen wir uns das gleiche Beispiel an, das oben in Nr. 1 beschrieben wurde, aber dieses Mal führen wir den Memcache ein.

    Beginnen wir, wenn ein Benutzer zum ersten Mal eine Seite besucht und sich nichts im Cache befindet. Sie beginnen mit der Abfrage von Tabelle A, die die IDs der 10 Einträge zurückgibt, die Sie auf der Seite anzeigen möchten. Für jeden dieser Einträge fragen Sie dann die Datenbank ab, um die diesem Eintrag zugeordneten Eigenschaften abzurufen, und verwenden dann diese Eigenschaften, um ein Objekt zu bilden, mit dem Ihr Code eine Schnittstelle herstellen kann (z. B. ein Objekt). Anschließend speichern Sie dieses Objekt (oder eine serialisierte Form dieses Objekts) im Memcache.

    Wenn jemand dieselbe Seite zum zweiten Mal lädt, beginnen Sie auf dieselbe Weise: indem Sie Tabelle A nach der Liste der angezeigten Eintrags-IDs abfragen. Gehen Sie für jeden Eintrag zuerst zum Memcache und sagen Sie: "Haben Sie den Eintrag #X im Cache?" Wenn ja, gibt memcache das Eingabeobjekt an Sie zurück. Wenn nicht, müssen Sie die Datenbank erneut abfragen, um ihre Eigenschaften abzurufen, das Objekt zu bilden und es im Memcache zu speichern. Meistens gibt es beim zweiten Besuch derselben Seite nur eine Datenbankabfrage. Alle anderen Daten werden dann direkt aus dem Memcache abgerufen.

    In der Praxis wurde für den größten Teil von LiveJournal festgestellt, dass die meisten Systemdaten, insbesondere die weniger flüchtigen Daten, im Memcache zwischengespeichert wurden und die zusätzlichen Abfragen an die Datenbank, die zur Unterstützung des Schmaltabellenschemas erforderlich waren, so gut wie vollständig ausgeglichen wurden.

    Dieses Design hat die Lösung des Problems beim Zusammenstellen einer Liste von Posts, die mit all Ihren Freunden verknüpft sind, zu einem Stream oder einer "Wand" erheblich vereinfacht .

  3. Als nächstes sollten Sie Ihre Datenbank partitionieren. Das oben beschriebene Modell weist ein weiteres Problem auf, und das heißt, Ihre schmalen Tabellen sind in der Regel sehr groß/lang. Und je mehr Zeilen diese Tabellen haben, desto schwieriger werden andere Verwaltungsaufgaben. Um dies auszugleichen, kann es sinnvoll sein, die Größe Ihrer Tabellen zu verwalten, indem Sie die Tabellen auf eine bestimmte Weise partitionieren, sodass Benutzercluster von einer Datenbank und ein anderer Benutzercluster von einer separaten Datenbank bereitgestellt werden. Dies verteilt die Last auf die Datenbank und hält Abfragen effizient.

  4. Schließlich benötigen Sie fantastische Indizes. Die Geschwindigkeit Ihrer Abfragen hängt weitgehend davon ab, wie gut die Tabellen Ihrer Datenbank indiziert sind. Ich werde nicht zu viel Zeit damit verbringen, darüber zu diskutieren, was ein Index ist, außer zu sagen, dass es einem riesigen Kartenkatalogsystem sehr ähnlich ist, Nadeln im Heuhaufen effizienter zu finden. Wenn Sie MySQL verwenden, empfehle ich, das langsame Abfrageprotokoll zu aktivieren, um nach Abfragen zu suchen, deren Erfüllung lange dauert. Wenn eine Abfrage auf Ihrem Radar angezeigt wird (z. B. weil sie langsam ist), finden Sie heraus, welchen Index Sie der Tabelle hinzufügen müssen, um sie zu beschleunigen.

"Danke für all diesen großartigen Hintergrund, aber heiliger Trottel, das ist eine Menge Code, den ich schreiben muss."

Nicht unbedingt. Es wurden viele Bibliotheken geschrieben, die die Anbindung an Memcache sehr einfach machen. Wieder andere Bibliotheken haben den gesamten oben beschriebenen Prozess kodifiziert. Data :: ObjectDriver in Perl ist eine solche Bibliothek. Wie bei anderen Sprachen müssen Sie selbst recherchieren.

Ich hoffe, Sie fanden diese Antwort hilfreich. Was ich häufig festgestellt habe, ist, dass die Skalierbarkeit eines Systems häufig immer weniger auf Code und immer mehr auf eine solide Datenspeicherungs- und -verwaltungsstrategie/technisches Design zurückzuführen ist.

41
Byrne Reese

Was ist für Websites, die hoch skalierbar sein müssen, wie z. B. soziale Netzwerke wie Facebook, der beste Weg, um die Website zu gestalten?

Messen.

Ich würde denken, die ...

Schlechte Politik.

Die tatsächliche Messung ist erforderlich.

13
S.Lott

Die Skalierbarkeit hängt nicht von bestimmten Implementierungsstrategien ab, sondern vom Entwerfen Ihrer Anwendungsarchitektur, sodass sich die Datenzugriffsschicht ohne massives Refactoring und Umschreiben weiterentwickeln kann.

Eine wichtige Technik beim Aufbau eines skalierbaren Systems besteht darin, Ihre allgemeinen Datenzugriffsanforderungen zu verstehen und einen Schnittstellenvertrag zu erstellen. Beispielsweise müssen Sie möglicherweise einen Benutzer abrufen oder die 50 Fotos auflisten, die zuletzt von einem Benutzer veröffentlicht wurden.

Sie benötigen nicht unbedingt einen Netzwerkkanal zwischen Ihrer Geschäftslogik für Anwendungen und der Datenzugriffslogik. Eine Methodenaufruf-Indirektion mit einer Methode pro logischer Operation würde gut funktionieren, um zu starten.

Machen Sie diese Datenzugriffsmethoden zunächst so einfach wie möglich. Es ist sehr schwer vorherzusagen, wo die Leistungsprobleme liegen werden, bis Ihre Anwendung echte Nutzungsmuster bedient und Sie Daten darüber sammeln, wo Sie Engpässe haben.

Durch eine gut definierte Datenzugriffsschnittstelle können Sie Ihre Datenzugriffsimplementierung weiterentwickeln, ohne umfassende Änderungen an Ihrer gesamten Anwendung vorzunehmen. Sie können auch entscheiden, zu einer Webdienstarchitektur zu wechseln, die für Ihre Geschäftslogik transparent ist.

Viele der obigen Antworten geben einige gute Ratschläge, wie Sie vorgehen sollen, wenn Sie Ihre Leistungsengpässe entdeckt haben. Wenn Sie diese jedoch zu früh anwenden, können Sie durch die Komplexität Ihres Codes behindert werden, bevor Sie wissen, ob diese Komplexität überhaupt erforderlich ist.

9
Martin Atkins

Entwickeln Sie eine einfache Website und lassen Sie sie ein gewisses Verkehrsniveau erreichen. In diesem Sinne lernen Sie, wie Sie skalierbare Websites erstellen.

Bis Sie sich dem Problem stellen, können Sie sich keine Lösung vorstellen.

Vertrauen Sie mir, sobald die Website rollt und die Skalierungsanforderungen erfüllt sind, werden Sie auf jeden Fall wissen, wie das geht. :-)

4
Pankaj Upadhyay

Es ist allgemein bekannt, dass Webanwendungen standardmäßig mit drei Ebenen entworfen werden sollten - Web- (Präsentations-), Anwendungs- und Datenbankebenen. Diese Aufteilung ist auf unterschiedliche Anforderungen in jeder der Schichten zurückzuführen - in der Regel qualitativ hochwertiger Festplattenzugriff/-speicher für die Datenbank, hohe CPU/Speicher auf der App-Schicht und hohe externe Bandbreite/Speicher/geografische Streuung auf der Webebene. Die Anwendungs-/Datenbankschicht wird häufig bis viel später im Lebenszyklus der Anwendung zu einer zusammengeführt, da Datenbankcomputer häufig massive Server sind, die auch für die frühe Anwendungslast erstellt werden können.

Die spezifische Anzahl von Ebenen und die geeignete Architektur für Ihre Anwendung müssen jedoch nicht mit diesem oder einem anderen Modell übereinstimmen.

Planen Sie, alle Aktivitäten in Ihrem System zu messen und zu überwachen. Beginnen Sie mit einem zwei- oder dreistufigen Design und konzentrieren Sie sich auf die Teile, die beim Erstellen die meisten Ressourcen erfordern. Lassen Sie die laufende Anwendung Ihr Design auf dieser Ebene leiten. Je mehr Informationen Sie sammeln und je genauer und detaillierter diese sind, desto bessere Entscheidungen können Sie über das Entwerfen der Anwendung treffen, wenn sie wächst.

Wählen Sie ein Framework und eine Architektur, mit denen Sie später die erforderlichen Änderungen so schnell und schmerzlos wie möglich vornehmen können. Selbst wenn Ihr Datenzugriff/Ihre Speicherung/Verarbeitung und Ihre Anwendungsverarbeitung in derselben ausführbaren Datei ausgeführt werden, wird es beispielsweise später nicht so schwierig sein, sie in zwei Ebenen aufzuteilen, wenn sie richtig berücksichtigt werden.

2
blueberryfields

Jeder zusätzliche Schritt beim Herstellen einer Verbindung zur Datenbank ist nur ein Aufwand. Zum Beispiel zwischen UI -> Business Facade -> Business -> Data Access -> Database und UI -> Database ist der zweite Ansatz schneller. Je mehr Schritte Sie entfernen, desto weniger wartbar wird Ihr System und desto mehr Duplikate werden angezeigt. Stellen Sie sich vor, Sie schreiben den erforderlichen Code, um die Liste der Freunde im Profil, auf der Startseite, auf der Seite zur Verwaltung von Freunden usw. abzurufen.

Sie sollten hier also ein Gleichgewicht zwischen höherer Leistung (was sich natürlich direkt auf eine höhere Skalierbarkeit auswirkt) und besserer Wartbarkeit herstellen .

Beschränken Sie sich jedoch nicht auf das Thema Datenbankverbindung , wenn Sie hochskalierbare Websites erstellen möchten. Berücksichtigen Sie auch diese Punkte:

  1. Auswahl der richtigen Plattform (PHP ist aufgrund seiner Skripterstellung schneller, aber ASP.NET muss die angeforderte Datei im laufenden Betrieb kompilieren, um sie zu verarbeiten und etwas bereitzustellen. Außerdem soll node.js mehr sein skalierbar aufgrund seiner Callback-basierte Architektur )
  2. Verwenden der RESTful-Architektur anstelle des Webdienstmodells (SOA)
  3. Verwendung von JSON für die Datenübertragung anstelle von XML (was dazu führt, dass weniger Bytes übertragen werden müssen)
  4. Befolgen Sie Yahoo Leistungsrichtlinien
  5. Netzwerk- und Hardwarethemen wie Lastausgleich oder Tier-Architektur
2
Saeed Neamati

Es gibt zwei Hauptmethoden zum Skalieren: Vergrößern und Verkleinern.

Beim Skalieren wird eine Maschine durch eine leistungsstärkere ersetzt. Skalieren bedeutet, eine weitere Maschine hinzuzufügen, um die Arbeit zu erledigen, die vorhandene Maschinen ausführen.

Jede stark frequentierte Website muss skalierbar sein. Die Softwarearchitektur muss so gestaltet werden, dass mehr Maschinen hinzugefügt werden können, je geschäftiger die Site wird.

Normalerweise bedeutet dies, die Anwendung in Ebenen aufzuteilen, damit auf jeder Ebene mehr Server angeschlossen und abgespielt werden können.

Ich würde Option 1 machen, einen Service haben, anstatt ihn direkt zu machen. Sie können bisher nur eine monolithische Anwendung skalieren.

1
Jon Raynor

Entwickeln Sie Ihre Site mithilfe einer Technologieplattform, die die Cloud vollständig unterstützt.

0
bhagyas