2013-05-16 17 views
6

Sie möchten die Cachedaten zwischen zwei Servern synchronisieren. Beide Datenbanken teilen die gleiche Datenbank, aber für bessere Ausführungsdaten habe ich die Daten beim Start in Hash Map zwischengespeichert. Daher möchten Sie die zwischengespeicherten Daten synchronisieren, ohne Server neu zu starten. (Beide Server starten gleichzeitig).Die beste Methode zum Synchronisieren von Cachedaten zwischen zwei Servern

Bitte schlagen Sie mir die beste und effiziente Möglichkeit vor.

Antwort

22

Anstatt zu versuchen, die zwischengespeicherten Daten zwischen zwei Serverinstanzen zu synchronisieren, warum zentralisieren Sie das Caching statt mit etwas wie memcached/couchbase oder redis? Die Verwendung von verteilter Caching mit etwas wie EHCACHE ist viel komplizierter und fehleranfällig IMO vs die Zentralisierung der zwischengespeicherten Daten mit einem Caching-Server wie die genannten.

Als Ergänzung zu meiner ursprünglichen Antwort, bei der Entscheidung, welche Caching-Ansatz zu verwenden (im Speicher, zentralisierte), eine Sache zu berücksichtigen ist die Volatilität der Daten, die zwischengespeichert werden.

Wenn die Daten in der Datenbank gespeichert werden, sich aber nicht ändern, nachdem die Server sie geladen haben, ist keine Synchronisierung zwischen den Servern erforderlich. Lass sie einfach diese statischen Daten von der Quelle in den Speicher laden und dann ihre fröhlichen Wege gehen, was auch immer sie tun. Die Daten werden sich nicht ändern, so dass kein kompliziertes Muster für die Synchronisierung der Daten zwischen den Servern erforderlich ist.

Wenn es in der Tat eine gewisse Volatilität in den Daten gibt (wie Sie Caching nachgeschlagenen Entitätsdaten aus der Datenbank suchen, um Treffer in der DB zu speichern), denke ich immer noch, zentralisierte Caching ist ein besserer Ansatz als in -memory verteilte und synchronisierte Zwischenspeicherung. Sie müssen nur sicherstellen, dass Sie einen geeigneten Ablauf für die zwischengespeicherten Daten verwenden, um eine natürliche Aktualisierung der Daten von Zeit zu Zeit zu ermöglichen. Sie können die zwischengespeicherten Daten auch einfach aus dem zentralen Speicher löschen, wenn sie sich im Aktualisierungspfad für eine bestimmte Entität befinden, und sie dann bei der nächsten Anforderung für diese Daten einfach erneut aus dem Cache laden. Dies ist IMO besser als ein echter Write-Through-Cache, bei dem Sie sowohl in den zugrunde liegenden Speicher als auch in den Cache schreiben. Die Datenbank selbst kann die Daten optimieren (z. B. über standardmäßige nicht versorgte Werte), und Ihre zwischengespeicherten Daten stimmen in diesem Fall möglicherweise nicht mit denen in der Datenbank überein.

EDIT:

Eine Frage wurde in den Kommentaren über die Vorteile eines zentralisierten Cache (Ich vermute, gegen so etwas wie ein im Speicher verteilten Cache) gefragt. Ich werde meine Meinung dazu abgeben, aber zuerst einen Standard Disclaimer. Zentralisiertes Caching ist kein Allheilmittel. Es zielt darauf ab, spezifische Probleme im Zusammenhang mit In-jvm-Speicher-Caching zu lösen. Bevor Sie sich entscheiden, ob Sie zu diesem Thema wechseln oder nicht, sollten Sie zuerst Ihre Probleme verstehen und herausfinden, ob sie zu den Vorteilen des zentralisierten Caching passen. Zentralisiertes Caching ist eine architektonische Veränderung und kann mit eigenen Problemen/Vorbehalten einhergehen. Wechseln Sie nicht zu einfach, weil jemand sagt, es ist besser als das, was Sie tun. Stellen Sie sicher, dass der Grund für das Problem passt.

Okay, jetzt auf meine Meinung für welche Arten von Problemen kann zentralisiertes Caching vs in-jvm-Speicher (und möglicherweise verteilt) Caching zu lösen. Ich werde zwei Dinge aufzählen, obwohl ich sicher bin, dass es noch ein paar mehr gibt. Meine zwei großen sind: Gesamtspeicherplatz und Datensynchronisierung Probleme.

Beginnen wir mit Gesamtspeicherabdruck. Angenommen, Sie führen ein Standard-Entity-Caching durch, um Ihre relationale Datenbank vor unnötigem Stress zu schützen. Lassen Sie uns auch sagen, dass Sie eine Menge Daten zwischenspeichern müssen, um Ihre DB wirklich zu schützen; sagen im Bereich vieler GBs.Wenn Sie in-jvm-Speicher zwischenspeichern, und Sie sagen, dass 10 App-Server-Boxen hatten, müssten Sie diese zusätzlichen Speicher ($$$) mal 10 für jede der Boxen, die das Zwischenspeichern in jvm tun müssten Erinnerung. Außerdem müssten Sie Ihrer JVM einen größeren Heap zuordnen, um die zwischengespeicherten Daten zu speichern. Ich bin der Meinung, dass der JVM-Heap klein und schlank sein sollte, um die Müllsammlung zu erleichtern. Wenn Sie große Teile von Old Gen haben, die nicht gesammelt werden können, dann werden Sie Ihren Garbage Collector betonen, wenn er in einen vollständigen GC geht und versucht, etwas aus dem aufgeblähten Old Gen Space zu holen. Sie möchten lange GC2-Pausenzeiten vermeiden und Blähungen, mit denen Ihre alte Generation nicht fertig wird. Wenn Ihre Speicheranforderung über einem bestimmten Schwellenwert liegt und Sie zufällig 32-Bit-Maschinen für Ihre App-Ebene ausführen, müssen Sie auf 64-Bit-Maschinen aufrüsten, was wiederum zu hohen Kosten führen kann.

Wenn Sie nun stattdessen die zwischengespeicherten Daten zentralisieren (mit Redis oder Memcached), könnten Sie den Gesamtspeicherbedarf der zwischengespeicherten Daten erheblich reduzieren, da Sie diese auf einigen Boxen statt auf allen haben könnten App-Server-Boxen in der App-Ebene. Wahrscheinlich möchten Sie einen Cluster-Ansatz verwenden (beide Technologien unterstützen ihn) und mindestens zwei Server, um Ihnen eine hohe Verfügbarkeit zu geben und einen einzelnen Fehlerpunkt in Ihrer Caching-Schicht zu vermeiden (mehr dazu in einer Sekunde). Indem Sie ein paar Maschinen haben, um die benötigte Speicheranforderung für das Zwischenspeichern zu unterstützen, können Sie einige beträchtliche $$ sparen. Außerdem können Sie die App-Boxen und die Cache-Boxen jetzt anders einstellen, da sie unterschiedlichen Zwecken dienen. Die App-Boxen können für hohen Durchsatz und niedrigen Heap eingestellt werden, und die Cache-Boxen können auf großen Speicher abgestimmt werden. Und kleinere Häufungen helfen definitiv beim Gesamtdurchsatz der App-Layer-Boxen.

Jetzt ein schneller Punkt für das zentralisierte Caching im Allgemeinen. Sie sollten Ihre Anwendung so einrichten, dass sie auch ohne den Cache überleben kann, falls sie für eine bestimmte Zeit komplett ausfällt. Beim traditionellen Zwischenspeichern von Entitäten bedeutet dies, dass wenn Sie den Cache vollständig nicht verfügbar machen, Sie Ihre Datenbank direkt für jede Anfrage treffen. Nicht toll, aber auch nicht das Ende der Welt.

Okay, jetzt für Probleme bei der Datensynchronisierung. Bei verteilter In-JVM-Speicher-Zwischenspeicherung müssen Sie den Cache synchron halten. Eine Änderung an zwischengespeicherten Daten in einem Knoten muss zu den anderen Knoten repliziert werden und in ihre zwischengespeicherten Daten synchronisiert werden. Dieser Ansatz ist ein wenig beängstigend, wenn aus irgendeinem Grund (zum Beispiel Netzwerkausfall) einer der Knoten nicht mehr synchron ist, wenn eine Anfrage an diesen Knoten geht, sind die Daten, die der Benutzer sieht, nicht genau mit denen, die gegenwärtig in der DB. Schlimmer noch, wenn sie eine andere Anfrage machen und einen anderen Knoten treffen, werden sie andere Daten sehen, und das wird für den Benutzer verwirrend sein. Durch die Zentralisierung der Daten beseitigen Sie dieses Problem. Nun könnte man argumentieren, dass der zentralisierte Cache eine Steuerung des gemeinsamen Zugriffs um Aktualisierungen für den gleichen zwischengespeicherten Datenschlüssel benötigt. Wenn zwei gleichzeitige Updates für denselben Schlüssel verfügbar sind, wie stellen Sie sicher, dass sich die beiden Updates nicht gegenseitig stampfen? Mein Gedanke hier ist, sich nicht einmal darum zu sorgen; Wenn eine Aktualisierung stattfindet, lassen Sie das Element aus dem Cache (und schreiben Sie es direkt in die Datenbank) und lassen Sie es beim nächsten Lesevorgang erneut laden. Es ist sicherer und einfacher so. Wenn Sie dies nicht tun möchten, können Sie die CAS-Funktion (Check-And-Set) anstelle der optimistischen Steuerung des gemeinsamen Zugriffs verwenden, wenn Sie sowohl den Cache als auch die Aktualisierung der Datenbank aktualisieren möchten.

Kurz gesagt, Sie können Geld sparen und Ihre App-Layer-Maschinen optimieren, wenn Sie die Daten, die sie zwischenspeichern, zentralisieren. Sie können auch eine bessere Genauigkeit dieser Daten erzielen, da weniger Probleme mit der Datensynchronisierung auftreten. Ich hoffe das hilft.

+0

Danke für die Antwort. Können Sie nur die Vorteile von zentralisiertem Cache erklären, da dies wiederum den Overhead auf meinem Server erhöhen kann. Gegenwärtig hat es ungefähr 5000 gleichzeitige Benutzer. Hinweis: nach aktuellen Statistiken jetzt bekomme ich auch Speicher zu einer bestimmten Zeit aus dem Schrank. –

+0

Durch Antwort aktualisiert, um einige Vorteile zu enthalten ... – cmbaxter

+0

Danke Cmbaxter ... Das hilft wirklich ... –

8

Zuerst versuchen Sie, die vorzeitige Optimierung zu vergessen. Brauchst du den Cache wirklich? 99%, dass Sie es nicht brauchen. In diesem Fall entfernen Sie den redundanten Code.

Wenn Sie es jedoch brauchen, versuchen Sie aufzuhören Räder neu zu erfinden. Es gibt perfekt vorbereitete Bibliotheken. Zum Beispiel ehCache, die verteilte Modus hat.

+0

Danke für die Antwort. Ich habe ungefähr 5000 gleichzeitige Benutzer, also kann ich Cache nicht entfernen, nehme ich an. werde über ehCache suchen ... –

2

Verwenden Sie HazelCast. Es ermöglicht die Datensynchronisation zwischen Servern mit Multicast-Protokoll. Es ist einfach zu bedienen. Es unterstützt Sperren und andere Funktionen.