Welches sind die besten Ansätze für das Clustering/die Verteilung einer Java-Server-Anwendung? Ich bin auf der Suche nach einem Ansatz, der eine horizontale Skalierung durch Hinzufügen weiterer Anwendungsserver und Datenbankserver ermöglicht.
- Welche Technologien (Software-Engineering-Techniken oder spezifische Technologien) würden Sie vorschlagen, um diese Art von Problem anzugehen?
- Welche Techniken verwenden Sie, um eine Persistenzschicht so zu gestalten, dass sie für viele Leser/Schreiber skalierbar ist? Skalierung von Anwendungstransaktionen und Skalierung des Zugriffs auf gemeinsam genutzte Daten (der beste Ansatz ist die Beseitigung gemeinsam genutzter Daten; welche Techniken können Sie anwenden, um gemeinsam genutzte Daten zu beseitigen).
- Unterschiedliche Ansätze scheinen erforderlich zu sein, je nachdem, ob Ihre Transaktionen lese- oder schreiblastig sind, aber ich habe das Gefühl, dass, wenn Sie eine "schreiblastige" Anwendung optimieren können, diese auch für "leselastig" effizient wäre.
Die "beste" Lösung würde es Ihnen ermöglichen, eine Java-Anwendung für einen einzelnen Knoten zu schreiben und hoffentlich die meisten Details des Zugriffs auf/der Sperrung von gemeinsam genutzten Daten zu "verstecken".
In einer verteilten Umgebung besteht das schwierigste Problem immer darin, dass mehrere Transaktionen auf gemeinsame Daten zugreifen. Es scheint, als gäbe es 2 gängige Ansätze für gleichzeitige Transaktionen.
- Explizite Sperren (was extrem fehleranfällig und langsam bei der Koordinierung über mehrere Knoten in einem verteilten System ist)
- Software-Transaktionsspeicher (STM), auch bekannt als optimistische Parallelität, bei der eine Transaktion während eines Commits zurückgerollt wird, wenn sie feststellt, dass sich der gemeinsame Zustand geändert hat (und die Transaktion später erneut durchgeführt werden kann). Welcher Ansatz ist besser skalierbar und was sind die Kompromisse in einem verteilten System?
Ich habe mich mit Skalierungslösungen (und allgemein mit Anwendungen, die ein Beispiel für die Skalierung bieten) beschäftigt, wie z. B.:
- Terrakotta - bietet eine "transparente" Skalierung durch die Erweiterung des Java-Speichermodells um einen verteilten gemeinsamen Speicher unter Verwendung von Javas Gleichzeitigkeits-Sperrmechanismus (synchronisierte, ReentrantReadWriteLocks).
- Google App Engine Java - Ermöglicht das Schreiben von Java- (oder Python)-Anwendungen, die auf "Cloud"-Servern verteilt werden, wobei Sie verteilen, welcher Server eine Transaktion abwickelt, und Sie BigTable zum Speichern Ihrer persistenten Daten verwenden (ich bin nicht sicher, wie Sie Transaktionen, die auf gemeinsam genutzte Daten zugreifen, oder Sperrkonflikte handhaben, um effektiv skalieren zu können)
- Darkstar MMO Server - Darkstar ist ein quelloffener MMO (Massively Multiplayer Online)-Spieleserver von Sun. Sie skalieren Transaktionen auf eine thread-transaktionale Art und Weise, die es einer bestimmten Transaktion erlaubt, nur für eine bestimmte Zeitspanne zu laufen und sich zu binden, und wenn sie zu lange dauert, wird sie zurückgerollt (eine Art softwaretransaktionaler Speicher). Sie forschen in folgenden Bereichen Unterstützung einer Multi-Node-Server-Konfiguration für die Skalierung.
- Hibernate's optimistisches Sperren - Wenn Sie Hibernate verwenden, können Sie deren optimistische Gleichzeitigkeitsunterstützung nutzen, um die Software-Transaktionsspeicher Typverhalten
- Apache CouchDB soll natürlich auf viele Leser/Schreiber-DBs in einer Mesh-Konfiguration "skalieren". (Gibt es ein gutes Beispiel dafür, wie Sie das Sperren von Daten oder die Gewährleistung der Transaktionsisolation handhaben?):
- JCache - Skalierung "leseintensiver" Anwendungen durch Zwischenspeichern der Ergebnisse häufiger Abfragen, die Sie in der Google Appengine für den Zugriff auf Memcached und zum Zwischenspeichern anderer häufig gelesener Daten verwenden können.
Terracotta scheint die vollständigste Lösung zu sein, da man eine bestehende Serveranwendung "einfach" modifizieren kann, um die Skalierung zu unterstützen (nachdem man @Root-Objekte und @AutoLockRead/Write-Methoden definiert hat). Das Problem ist, dass die Optimierung für verteilte Systeme kein nachträglicher Gedanke ist, wenn man wirklich das Maximum an Leistung aus einer verteilten Anwendung herausholen will - man muss sie sozusagen mit dem Wissen entwerfen, dass der Objektzugriff möglicherweise durch Netzwerk-E/A blockiert werden könnte.
Um richtig zu skalieren, scheint es immer auf die Partitionierung von Daten und den Lastausgleich von Transaktionen anzukommen, so dass eine bestimmte "Ausführungseinheit" (CPU-Kern -> Thread -> verteilter Anwendungsknoten -> DB-Masterknoten)
Um eine Anwendung durch Clustering richtig skalieren zu können, müssen Sie in der Lage sein, Ihre Transaktionen in Bezug auf ihre Lese- und Schreibvorgänge zu partitionieren. Welche Lösungen haben die Menschen mit, um ihre Anwendungen Daten (Oracle, Google BigTable, MySQL, Data Warehousing) zu verteilen, und im Allgemeinen, wie Sie Partitionierung von Daten (viele Schreib-Master, mit vielen mehr lesen DBs usw.) zu verwalten.
In Bezug auf die Skalierung Ihrer Datenpersistenzschicht, welche Art von Konfiguration skaliert die beste in Bezug auf die Partitionierung Ihrer Daten auf viele Leser/viele Schreiber (in der Regel würde ich meine Daten auf der Grundlage eines bestimmten Benutzers (oder was auch immer Kern Entität, die in der Regel Ihre "Root"-Objekt-Entität) im Besitz von einem einzigen Master-DB) partitionieren