Heim > Artikel > Backend-Entwicklung > Bezüglich Ruhezustand-Cache-Problemen:
1. Über Ruhezustand-Cache:
Grundlegende Cache-Prinzipien
Der Ruhezustand-Cache wird in der Sitzung gespeichert und als „erster Level-Cache“ bezeichnet standardmäßig installiert und kann nicht deinstalliert werden.
Die zweite Ebene ist der von sessionFactory gesteuerte Cache auf Prozessebene. Es handelt sich um einen global gemeinsam genutzten Cache, und jede Abfragemethode, die den Cache der zweiten Ebene aufruft, profitiert davon. Der Second-Level-Cache funktioniert nur, wenn er richtig konfiguriert ist. Gleichzeitig muss bei bedingten Abfragen die entsprechende Methode verwendet werden, um Daten aus dem Cache abzurufen. Zum Beispiel die Methode „Query.iterate()“, die Methode „load“, „get“ usw. Es ist zu beachten, dass die Methode session.find immer Daten aus der Datenbank abruft und keine Daten aus dem Cache der zweiten Ebene abruft, selbst wenn dieser die erforderlichen Daten enthält.
Der Implementierungsprozess der Verwendung des Caches beim Abfragen ist: Fragen Sie zuerst ab, ob sich die erforderlichen Daten im Cache der ersten Ebene befinden. Wenn nicht, fragen Sie den Cache der zweiten Ebene ab , und führen Sie dann die Abfragedatenbank Work aus. Es ist zu beachten, dass die Abfragegeschwindigkeit dieser drei Methoden nacheinander abnimmt.
1.2. Vorhandene Probleme
1.2.1. Probleme mit dem First-Level-Cache und die Gründe für die Verwendung des Second-Level-Cache
Da die Lebensdauer der Sitzung oft sehr kurz ist, ist die First-Level-Cache am schnellsten Cache, der innerhalb der Sitzung vorhanden ist. Natürlich ist der Lebenszyklus auch sehr kurz, sodass die Trefferquote des Caches der ersten Ebene sehr niedrig ist. Auch die Verbesserung der Systemleistung ist sehr begrenzt. Die Hauptfunktion dieses internen Sitzungscache besteht natürlich darin, den internen Datenstatus der Sitzung synchron zu halten. Es wird vom Ruhezustand nicht bereitgestellt, um die Systemleistung erheblich zu verbessern.
Um die Leistung der Verwendung des Ruhezustands zu verbessern, müssen Sie zusätzlich zu einigen herkömmlichen Methoden, die Aufmerksamkeit erfordern, wie z. B.:
Verzögertes Laden, dringende externe Verbindungen, Abfragefilterung usw. verwenden, auch den zweiten Ruhezustand konfigurieren -Level-Cache. Die Verbesserung der Gesamtleistung des Systems hat oft sofortige Ergebnisse!
(Aufgrund meiner Erfahrung in früheren Projekten wird es im Allgemeinen eine 3- bis 4-fache Leistungsverbesserung geben)
Das Problem mit N+1-Abfragen
Iterieren Sie beim Ausführen einer bedingten Abfrage ( )-Methode hat das berühmte „n+1“-Abfrageproblem, was bedeutet, dass die Iterate-Methode in der ersten Abfrage die Anzahl der Abfrageergebnisse ausführt, die die Bedingungen erfüllen, plus eine (n+1)-Abfrage. Dieses Problem besteht jedoch nur bei der ersten Abfrage und die Leistung wird erheblich verbessert, wenn dieselbe Abfrage später ausgeführt wird. Diese Methode eignet sich für die Abfrage von Geschäftsdaten mit großen Datenmengen.
Aber beachten Sie: Wenn die Datenmenge besonders groß ist (z. B. Pipeline-Daten usw.), müssen Sie die spezifische Cache-Strategie für dieses persistente Objekt konfigurieren, z. B. die Festlegung der maximalen Anzahl von Datensätzen, die im Cache vorhanden sind , die Cache-Existenzzeit und andere Parameter, um zu verhindern, dass das System eine große Datenmenge gleichzeitig in den Speicher lädt, was zu einer schnellen Erschöpfung der Speicherressourcen führt und tatsächlich die Leistung des Systems verringert! ! !
1.3. Weitere Überlegungen zur Verwendung des Second-Level-Cache:
1.3.1 Informationen zur Gültigkeit von Daten
Darüber hinaus verwaltet Hibernate die Daten selbst im Second-Level-Cache Stellen Sie sicher, dass die Daten im Cache mit den tatsächlichen Daten in der Datenbank übereinstimmen! Immer wenn Sie ein Objekt durch Aufrufen der Methoden save(), update() oder saveOrUpdate() übergeben oder ein Objekt mithilfe der Methoden load(), get(), list(), iterate() oder scroll() abrufen, Das Objekt wird zum internen Cache der Sitzung hinzugefügt. Beim anschließenden Aufruf der Methode „flush()“ wird der Zustand des Objekts mit der Datenbank synchronisiert.
Das heißt, beim Löschen, Aktualisieren oder Hinzufügen von Daten wird gleichzeitig der Cache aktualisiert. Dazu gehört natürlich auch der L2-Cache!
Solange die Hibernate-API aufgerufen wird, um datenbankbezogene Arbeiten auszuführen. Hibernate stellt automatisch die Gültigkeit der zwischengespeicherten Daten für Sie sicher! !
Wenn Sie jedoch JDBC verwenden, um den Ruhezustand zu umgehen und Vorgänge direkt in der Datenbank auszuführen. Zu diesem Zeitpunkt kann/kann Hibernate die an der Datenbank vorgenommenen Änderungen nicht selbstständig erkennen und kann die Gültigkeit der Daten im Cache nicht mehr garantieren! !
Dies ist auch ein Problem, das allen ORM-Produkten gemeinsam ist. Glücklicherweise stellt uns Hibernate die Cache-Löschmethode zur Verfügung, die uns die Möglichkeit gibt, die Datengültigkeit manuell sicherzustellen! !
Der Cache der ersten Ebene und der Cache der zweiten Ebene verfügen über entsprechende Löschmethoden.
Die vom Cache der zweiten Ebene bereitgestellten Löschmethoden sind:
Löschen des Caches nach Objektklasse
Löschen des Caches nach Objektklasse und Primärschlüssel-ID des Objekts
Löschen der zwischengespeicherten Daten bei der Sammlung von Gegenständen usw.
1.3.2. Geeignete Situationen
Nicht alle Situationen sind für die Verwendung des Second-Level-Cache geeignet und dies muss entsprechend der spezifischen Situation entschieden werden. Gleichzeitig können Sie eine bestimmte Cache-Strategie für ein persistentes Objekt konfigurieren.
Geeignet für die Verwendung von Second-Level-Cache:
1. Die Daten werden nicht von Dritten geändert.
Unter normalen Umständen ist es am besten, die Daten nicht so zu konfigurieren wird durch einen anderen Cache als den Ruhezustand geändert, um inkonsistente Daten zu vermeiden. Wenn diese Daten jedoch aus Leistungsgründen zwischengespeichert werden müssen und möglicherweise von einem Dritten wie SQL geändert werden, können Sie auch einen sekundären Cache dafür konfigurieren. Sie müssen lediglich die Cache-Löschmethode manuell aufrufen, nachdem die SQL geändert wurde. Um die Datenkonsistenz sicherzustellen
2. Die Datengröße liegt im akzeptablen Bereich
Wenn die Datenmenge in der Datentabelle besonders groß ist, ist sie derzeit nicht für den sekundären Cache geeignet . Der Grund dafür ist, dass zu viele zwischengespeicherte Daten zu Einschränkungen der Speicherressourcen führen können, was wiederum die Leistung verringert.
Wenn die Datenmenge in der Datentabelle besonders groß ist, aber häufig nur der neuere Teil der Daten verwendet wird. Zu diesem Zeitpunkt können Sie auch einen Second-Level-Cache dafür konfigurieren. Die Caching-Strategie ihrer Persistenzklasse muss jedoch separat konfiguriert werden, z. B. die maximale Anzahl von Caches, die Cache-Ablaufzeit usw., und diese Parameter müssen auf einen angemessenen Bereich reduziert werden (ein zu hoher Wert führt zu Einschränkungen der Speicherressourcen). ist er zu niedrig, wird das Caching von geringer Bedeutung sein).
3. Die Datenaktualisierungsfrequenz ist niedrig.
Bei Daten mit einer zu hohen Datenaktualisierungsfrequenz können die Kosten für die häufige Synchronisierung der Daten im Cache den durch die Abfrage erzielten Vorteilen entsprechen Daten im Cache. Die Nachteile und Vorteile heben sich auf. Caching ist derzeit von geringer Bedeutung.
4. Unkritische Daten (keine Finanzdaten usw.)
Finanzdaten usw. sind sehr wichtige Daten, und ungültige Daten dürfen auf keinen Fall erscheinen oder sein Aus Sicherheitsgründen ist es derzeit aus Sicherheitsgründen am besten, den Second-Level-Cache nicht zu verwenden.
Denn in dieser Zeit ist die Bedeutung von „Korrektheit“ weitaus größer als die Bedeutung von „Hochleistung“.
2. Empfehlungen für die Verwendung des Ruhezustands-Cache im aktuellen System
1.4 Aktuelle Situation
Im Allgemeinen gibt es drei Situationen im System, die den Ruhezustand umgehen, um Datenbankoperationen durchzuführen:
1. Mehrere Anwendungen greifen gleichzeitig auf eine Datenbank zu.
In diesem Fall führt die Verwendung des Hibernate-Cache der zweiten Ebene zwangsläufig zu Dateninkonsistenzen.
Zu diesem Zeitpunkt ist ein detailliertes Design erforderlich. Beispielsweise vermeidet das Design gleichzeitige Schreibvorgänge in derselben Datentabelle,
verwendet verschiedene Ebenen von Sperrmechanismen in der Datenbank usw.
2. Dynamische Tabelle
Die sogenannte „dynamische Tabelle“ bezieht sich auf eine Datentabelle, die automatisch entsprechend dem Betriebssystem des Benutzers erstellt wird, wenn das System ausgeführt wird.
Beispielsweise gehören „benutzerdefinierte Formulare“ und andere Funktionsmodule zur Entwicklung benutzerdefinierter Erweiterungen. Da die Datentabelle zur Laufzeit erstellt wird, kann keine Hibernate-Zuordnung durchgeführt werden. Daher kann der darauf ausgeführte Vorgang nur ein direkter Datenbank-JDBC-Vorgang sein, der den Ruhezustand umgeht.
Wenn die Daten in der dynamischen Tabelle zu diesem Zeitpunkt nicht zwischengespeichert sind, liegt kein Problem mit der Dateninkonsistenz vor.
Wenn Sie zu diesem Zeitpunkt Ihren eigenen Cache-Mechanismus entwerfen, rufen Sie einfach Ihre eigene Cache-Synchronisierungsmethode auf.
3. Bei Verwendung von SQL zum Stapellöschen der Tabelle mit persistenten Ruhezustandsobjekten
Nach dem Ausführen des Stapellöschvorgangs zu diesem Zeitpunkt sind die gelöschten Daten im Cache vorhanden.
Analyse:
Wenn Artikel 3 (SQL-Batch-Löschung) ausgeführt wird, können nachfolgende Abfragen nur auf die folgenden drei Arten erfolgen:
a. session.find()-Methode:
Gemäß dem vorherigen In Zusammenfassend fragt die Suchmethode nicht die Daten im Cache der zweiten Ebene ab, sondern fragt direkt die Datenbank ab.
Es gibt also kein Problem mit der Datenvalidität.
b. Wenn Sie die Iterate-Methode aufrufen, um eine bedingte Abfrage durchzuführen:
Je nach der Ausführungsmethode der Iterate-Abfragemethode wird die Datenbank jedes Mal nach dem ID-Wert abgefragt, der die Bedingungen erfüllt, und dann den erhalten Daten aus dem Cache basierend auf dieser ID werden nur ausgeführt, wenn keine Daten mit dieser ID im Cache vorhanden sind.
Wenn dieser Datensatz direkt von SQL gelöscht wurde, fragt iterate diese ID beim Ausführen nicht ab ID-Abfrage. Selbst wenn dieser Datensatz im Cache vorhanden ist, kann der Kunde ihn daher nicht abrufen und es liegt keine Inkonsistenz vor. (Diese Situation wurde durch Tests bestätigt)
c. Verwenden Sie die Get- oder Load-Methode, um nach der ID abzufragen:
Objektiv gesehen werden zu diesem Zeitpunkt abgelaufene Daten abgefragt. Da jedoch die SQL-Batch-Löschung im System im Allgemeinen
für zwischenbezogene Datentabellen ist, gilt für
Die Abfrage der Zwischenassoziationstabelle verwendet im Allgemeinen eine bedingte Abfrage. Die Wahrscheinlichkeit, eine bestimmte Assoziationsbeziehung anhand der ID abzufragen, ist daher nicht vorhanden.
Wenn ein Wertobjekt wirklich benötigt wird abgefragt nach ID Um eine Beziehung abzufragen, wird aufgrund der großen Datenmenge SQL zur Stapellöschung verwendet. Wenn diese beiden Bedingungen erfüllt sind, können Sie die Methode zum manuellen Löschen der Daten dieses Objekts im Cache der zweiten Ebene verwenden, um sicherzustellen, dass die Abfrage nach ID das richtige Ergebnis erhält!!
(Diese Situation ist seltener tritt wahrscheinlich auf)
1.5. Empfehlungen
1. Es wird empfohlen, die Daten des Datenpersistenzobjekts nicht direkt zu aktualisieren, es kann jedoch eine Stapellöschung durchgeführt werden. (Es gibt auch weniger Stellen im System, die Batch-Updates erfordern)
2. Wenn Sie SQL zum Aktualisieren von Daten verwenden müssen, müssen die zwischengespeicherten Daten dieses Objekts gelöscht werden. Rufen Sie
SessionFactory.evict(class)
SessionFactory.evict(class,id)
und andere Methoden auf.
3. Wenn die Menge der Batch-Löschdaten nicht groß ist, können Sie die Batch-Löschung von Hibernate direkt verwenden, sodass es kein Problem gibt, die durch die Ausführung von SQL im Hibernate erzeugte Cache-Datenkonsistenz zu umgehen.
4. Es wird nicht empfohlen, die Batch-Löschmethode von Hibernate zu verwenden, um große Mengen an Datensatzdaten zu löschen.
Der Grund dafür ist, dass beim Batch-Löschen im Ruhezustand eine Abfrageanweisung und n Löschanweisungen ausgeführt werden, die die Bedingungen erfüllen. Anstatt jeweils eine bedingte Löschanweisung auszuführen! !
Wenn viele Daten gelöscht werden müssen, kommt es zu einem großen Leistungsengpass! ! ! Wenn die stapelweise zu löschende Datenmenge groß ist, beispielsweise mehr als 50 Elemente, können JDBC verwendet werden, um sie direkt zu löschen. Dies hat den Vorteil, dass nur eine SQL-Löschanweisung ausgeführt wird und die Leistung erheblich verbessert wird. Gleichzeitig kann für das Problem der Cache-Datensynchronisierung der Ruhezustand verwendet werden, um die relevanten Daten im Cache der zweiten Ebene zu löschen.
Rufen Sie SessionFactory.evict(class); SessionFactory.evict(class,id) und andere Methoden auf.
Also für die allgemeine Entwicklung von Anwendungssystemen (ohne Cluster, verteilte Datensynchronisierungsprobleme usw.), da die SQL-Ausführung nur aufgerufen wird, wenn eine Stapellöschung von Zwischenassoziationstabellen und gleichzeitig die Zwischentabelle ausgeführt wird Zuordnungstabelle Im Allgemeinen ist es unwahrscheinlich, dass beim Ausführen einer bedingten Abfrage eine Abfrage anhand der ID ausgeführt wird. Daher können Sie zu diesem Zeitpunkt die SQL-Löschung direkt durchführen, ohne die Cache-Löschmethode aufzurufen. Dies führt in Zukunft nicht zu Datenvaliditätsproblemen, die durch die Konfiguration des Second-Level-Cache verursacht werden.
Einen Schritt zurück: Auch wenn die Methode zum Abfragen des Zwischentabellenobjekts anhand der ID in Zukunft tatsächlich aufgerufen wird, kann dies durch Aufrufen der Methode zum Löschen des Caches gelöst werden.
4. Spezifische Konfigurationsmethode
Soweit ich weiß, glauben viele Hibernate-Benutzer abergläubisch, dass „Hibernate Leistungsprobleme für uns selbst lösen wird“, wenn sie die entsprechenden Methoden aufrufen. „Der Ruhezustand ruft automatisch den Cache für alle unsere Vorgänge auf.“ Die tatsächliche Situation ist, dass der Ruhezustand uns zwar einen guten Caching-Mechanismus und eine erweiterte Cache-Framework-Unterstützung bietet, dieser jedoch korrekt aufgerufen werden muss, bevor er funktionieren kann. ! Daher sind die Leistungsprobleme, die durch die Verwendung des Ruhezustands auf vielen Systemen verursacht werden, tatsächlich nicht darauf zurückzuführen, dass der Ruhezustand ineffektiv oder schlecht ist, sondern darauf, dass Benutzer nicht richtig verstehen, wie er zu verwenden ist. Im Gegenteil: Bei richtiger Konfiguration werden Sie von der Leistung des Ruhezustands ziemlich „überrascht“ sein. Im Folgenden werde ich die spezifische Konfigurationsmethode erläutern.
ibernate bietet eine Cache-Schnittstelle der zweiten Ebene:
net.sf.hibernate.cache.Provider,
stellt auch eine Standardimplementierung net.sf bereit .cache.HashtableCacheProvider,
kann auch andere Implementierungen wie ehcache, jbosscache usw. konfigurieren.
Der spezifische Konfigurationsort befindet sich in der Datei hibernate.cfg.xml
Hinweis: Tatsächlich ist dies der Fall In der einzigen Konfiguration wird der Second-Level-Cache des Ruhezustands überhaupt nicht verwendet. Gleichzeitig spielt der Cache der ersten Ebene keine Rolle, da die Sitzung bei Verwendung des Ruhezustands meistens sofort geschlossen wird. Das Ergebnis ist, dass kein Cache verwendet wird und alle Ruhezustandsvorgänge direkt in der Datenbank ausgeführt werden! ! Die Leistung ist wie erwartet.
Der Schlüssel ist dieser
schreibgeschützt, Lese-/Schreibzugriff, transaktional usw.
Achten Sie dann darauf, wenn es sich um eine bedingte Abfrage oder eine Abfrage handelt, die alle Ergebnisse zurückgibt, die session.find( )-Methode wird verwendet. Daten aus dem Cache werden nicht abgerufen. Die zwischengespeicherten Daten werden nur angepasst, wenn die Methode query.iterate() aufgerufen wird.