Heim  >  Artikel  >  Datenbank  >  So stellen Sie die Konsistenz zwischen Redis-Cache und Datenbank sicher

So stellen Sie die Konsistenz zwischen Redis-Cache und Datenbank sicher

WBOY
WBOYnach vorne
2022-03-17 18:50:153119Durchsuche

Dieser Artikel vermittelt Ihnen relevantes Wissen über Redis. Er stellt hauptsächlich Fragen im Zusammenhang mit der Sicherstellung der Konsistenz des Redis-Caches und der Datenbank vor, einschließlich der Aktualisierung des Caches und der Datenbank usw. Ich hoffe, dass er für alle hilfreich ist .

So stellen Sie die Konsistenz zwischen Redis-Cache und Datenbank sicher

Empfohlenes Lernen: Redis-Lern-Tutorial

1. Vier Synchronisationsstrategien:

Um sicherzustellen, dass der Cache und die Datenbank doppelt geschrieben werden, gibt es 4 Möglichkeiten, also 4 Synchronisationsstrategien:

  1. Zuerst den Cache aktualisieren, dann die Datenbank aktualisieren;
  2. Zuerst den Cache aktualisieren, dann die Datenbank aktualisieren;
  3. Zuerst die Datenbank aktualisieren, dann den Cache.
  4. Von diesen 4 Synchronisationsstrategien müssen wir Folgendes vergleichen:

Welche Methode eignet sich besser zum Aktualisieren des Caches oder zum Löschen des Caches? Sollte zuerst die Datenbank oder zuerst der Cache betrieben werden?

2. Cache aktualisieren oder Cache löschen

Als nächstes analysieren wir, ob wir den Cache aktualisieren oder löschen sollten.

2.1 Cache aktualisieren

Vorteile

:Der Cache wird bei jeder Datenänderung rechtzeitig aktualisiert, sodass bei Abfragen weniger wahrscheinlich Fehler auftreten.

Nachteile

: Das Aktualisieren des Caches ist relativ teuer. Wenn die Daten komplexe Berechnungen durchlaufen müssen, bevor sie in den Cache geschrieben werden, wirken sich häufige Aktualisierungen des Caches auf die Leistung des Servers aus. Wenn es sich um ein Geschäftsszenario handelt, in dem Daten häufig geschrieben werden, ist das Lesen der Daten möglicherweise nicht möglich, wenn der Cache häufig aktualisiert wird. 2.2 Cache löschen

Vorteile

:Einfache Bedienung, egal ob der Aktualisierungsvorgang kompliziert ist oder nicht, die Daten im Cache werden direkt gelöscht.

Nachteile

: Nach dem Löschen des Caches fehlt der nächste Abfragecache und die Datenbank muss erneut gelesen werden. Aus dem obigen Vergleich geht hervor, dass das Löschen des Caches im Allgemeinen die bessere Lösung ist. 3. Sollte zuerst die Datenbank oder der Cache betrieben werden?

Zuerst löschen wir zuerst den Cache und aktualisieren zuerst die Datenbank und führen einen Vergleich durch, wenn fehlschlägt:

3.1 Zuerst den Cache löschen und dann die Datenbank aktualisieren


Bitte fügen Sie eine Bildbeschreibung hinzu出现失败时进行一个对比:

3.1 先删除缓存再更新数据库

So stellen Sie die Konsistenz zwischen Redis-Cache und Datenbank sicher
如上图,是先删除缓存再更新数据库,在出现失败时可能出现的问题:

  • 线程A删除缓存成功,线程A更新数据库失败;
  • 线程B从缓存中读取数据;由于缓存被删,进程B无法从缓存中得到数据,进而从数据库读取数据;此时数据库中的数据更新失败,线程B从数据库成功获取旧的数据,然后将数据更新到了缓存。
  • 最终,缓存和数据库的数据是一致的,但仍然是旧的数据

3.2 先更新数据库再删除缓存

So stellen Sie die Konsistenz zwischen Redis-Cache und Datenbank sicher
如上图,是先更新数据库再删除缓存,在出现失败时可能出现的问题:

  • 线程A更新数据库成功,线程A删除缓存失败;
  • 线程B读取缓存成功,由于缓存删除失败,所以线程B读取到的是缓存中旧的数据。
  • 最后线程A删除缓存成功,有别的线程访问缓存同样的数据,与数据库中的数据是一样。
  • 最终,缓存和数据库的数据是一致的,但是会有一些线程读到旧的数据。

经过上面的比较,我们发现在出现失败的时候,是无法明确分辨出先删缓存和先更新数据库哪个方式更好,以为它们都存在问题。后面我们会进一步对这两种方式进行比较,但是在这里我们先探讨一下,上述场景出现的问题,应该如何解决呢?

实际上,无论上面我们采用哪种方式去同步缓存与数据库,在第二步出现失败的时候,都建议采用重试机制解决,上面两幅图中已经画了。




下面我们再将先删缓存与先更新数据库,在没有出现失败时进行对比:
So stellen Sie die Konsistenz zwischen Redis-Cache und Datenbank sicher
如上图,是先删除缓存再更新数据库,在没有出现失败时 Wie oben gezeigt, wird zuerst der Cache und dann die Datenbank gelöscht Probleme, die im Fehlerfall auftreten können:

    🎜Thread A löscht den Cache erfolgreich, aber Thread A kann die Datenbank nicht aktualisieren. 🎜🎜Thread B liest Daten aus dem Cache B kann keine Daten aus dem Cache abrufen und liest dann Daten aus der Datenbank. Zu diesem Zeitpunkt ist die Datenaktualisierung in der Datenbank fehlgeschlagen. Thread B hat die alten Daten erfolgreich aus der Datenbank abgerufen und die Daten dann im Cache aktualisiert. 🎜🎜🎜Am Ende sind die Cache- und Datenbankdaten konsistent, aber es handelt sich immer noch um alte Daten🎜🎜
🎜3.2 Aktualisieren Sie zuerst die Datenbank und löschen Sie dann den Cache🎜🎜Bitte fügen Sie eine Bildbeschreibung hinzu🎜 Wie oben gezeigt, wird zuerst die Datenbank aktualisiert und dann der Cache gelöscht. Wann Fehler tritt auf Mögliche Probleme: 🎜
    🎜Thread A aktualisiert die Datenbank erfolgreich, aber Thread A kann den Cache nicht löschen; 🎜🎜Thread B liest den Cache erfolgreich, aber da das Löschen des Caches fehlschlägt, Thread B liest die alten Daten im Cache. 🎜🎜Schließlich löscht Thread A den Cache erfolgreich und andere Threads greifen auf dieselben Daten im Cache zu, die mit den Daten in der Datenbank identisch sind. 🎜🎜🎜Irgendwann sind die Cache- und Datenbankdaten konsistent, aber einige Threads lesen die alten Daten. 🎜🎜
🎜Nach dem obigen Vergleich haben wir festgestellt, dass es bei einem Fehler unmöglich ist, klar zu unterscheiden, welche Methode besser ist: zuerst den Cache löschen oder zuerst die Datenbank aktualisieren, da wir davon ausgehen, dass beides der Fall ist sie haben Probleme. Wir werden diese beiden Methoden später weiter vergleichen, aber hier diskutieren wir zunächst, wie die Probleme gelöst werden können, die in den oben genannten Szenarien auftreten. 🎜🎜Tatsächlich wird empfohlen, einen Wiederholungsmechanismus zu verwenden, wenn der zweite Schritt fehlschlägt, unabhängig davon, welche Methode wir zum Synchronisieren des Caches und der Datenbank verwenden, wie in den beiden Bildern oben dargestellt . 🎜


🎜Jetzt vergleichen wir das Löschen des Caches zuerst und das Aktualisieren der Datenbank zuerst und wenn kein Fehler vorliegt: 🎜Bitte fügen Sie eine Bildbeschreibung hinzu🎜 Wie oben gezeigt, wird zuerst der Cache und dann die Datenbank gelöscht aktualisiert. Es gibt keinen . Mögliche Probleme, wenn ein Fehler auftritt: 🎜<ul> <li>Thread A hat den Cache erfolgreich gelöscht; </li> <li>Thread B hat die Datenbank erfolgreich gelesen und die alten Daten abgerufen; </li> <li>Thread A werden Die neuen Daten wurden erfolgreich in der Datenbank aktualisiert. </li> <li>Es ist ersichtlich, dass die beiden Schritte von Prozess A erfolgreich waren, aber aufgrund der Parallelität hat Prozess B zwischen den beiden Schritten auf den Cache zugegriffen. <li>Das Endergebnis ist, dass alte Daten im Cache und neue Daten in der Datenbank gespeichert werden und die beiden Daten inkonsistent sind. </li> </ul> <p><strong></strong></p> <hr> Wie im Bild oben gezeigt, wird zuerst die Datenbank aktualisiert und dann der Cache gelöscht. Mögliche Probleme in <hr>: <p><img src="https://img.php.cn/upload/article/000/000/067/e73f1a06231a665bb67debaa27b6baf0-3.png" alt="So stellen Sie die Konsistenz zwischen Redis-Cache und Datenbank sicher"><br>Thread A hat die Datenbank erfolgreich aktualisiert; <code>没有出现失败时

Thread A hat den Cache erfolgreich gelöscht.
  • Es ist ersichtlich, dass
  • der endgültige Cache mit den Daten in der Datenbank übereinstimmt und beide die neuesten Daten sind
  • . Aber Thread B hat während dieses Vorgangs die alten Daten gelesen. Möglicherweise gibt es zwischen diesen beiden Schritten andere Threads wie Thread B, die die alten Daten im Cache lesen, aber da die Ausführungsgeschwindigkeit dieser beiden Schritte schneller ist, ist dies nicht der Fall groß. Wenn nach diesen beiden Schritten andere Prozesse zwischengespeicherte Daten lesen, treten keine ähnlichen Probleme wie bei Prozess B auf.
  • Abschließendes Fazit:

Nach dem Vergleich werden Sie feststellen, dass das Aktualisieren der Datenbank zuerst und dann das Löschen des Caches eine Lösung mit weniger Auswirkungen ist. Wenn der zweite Schritt fehlschlägt, kann das Problem mithilfe eines Wiederholungsmechanismus behoben werden. 4. Verzögertes doppeltes Löschen

Wir haben oben erwähnt, dass

wenn zuerst der Cache gelöscht und dann die Datenbank aktualisiert wird

es zu Dateninkonsistenzen kommen kann

, auch wenn kein Fehler vorliegt. Gibt es eine Möglichkeit, dieses Problem zu lösen, wenn wir diese Methode in tatsächlichen Anwendungen aus bestimmten Gründen wählen müssen? Die Antwort lautet: Ja, das heißt, die Strategie des verzögerten Doppellöschens ist wie folgt:

den Cache löschen; N Millisekunden schlafen; Cache erneut löschen.

	public void write(String key, Object data) {
        Redis.delKey(key);
        db.updateData(data);
        Thread.sleep(1000);
        Redis.delKey(key);
    }
  1. Löschen Sie den Cache nach einer gewissen Zeit des Blockierens erneut, um die inkonsistenten Daten im Cache während dieses Vorgangs zu löschen
  2. . Was die konkrete Zeit betrifft, müssen Sie die ungefähre Zeit Ihres Unternehmens ermitteln und sie entsprechend dieser Zeit festlegen.
  3. 4.1 Was tun, wenn die Architektur Lesen und Schreiben trennt?
  4. Wenn die Datenbank eine Lese-/Schreib-Trennarchitektur übernimmt, treten neue Probleme auf, wie unten gezeigt:
Zu diesem Zeitpunkt kamen zwei Anfragen, Anfrage A (Aktualisierungsvorgang) und Anfrage B (Abfragevorgang)

Fordern Sie A auf, einen Aktualisierungsvorgang durchzuführen und Redis zu löschen.

Fordern Sie die Hauptbibliothek auf, einen Aktualisierungsvorgang durchzuführen, und fordern Sie B auf, einen Abfragevorgang durchzuführen, und stellen Sie fest, dass keine vorhanden ist Daten in Redis;

Gehen Sie zur Slave-Bibliothek. Holen Sie sich die Daten. Die Datensynchronisierung ist zu diesem Zeitpunkt noch nicht abgeschlossen. Bei den erhaltenen Daten handelt es sich um alte Daten. Die Lösung besteht zu diesem Zeitpunkt darin, die Datenbank abzufragen Füllen Sie Daten in Redis aus und zwingen Sie sie dann, zur Abfrage auf die Hauptbibliothek zu verweisen.
So stellen Sie die Konsistenz zwischen Redis-Cache und Datenbank sicher
Was soll ich tun, wenn der Löschvorgang fehlschlägt?

  1. Wenn der Löschvorgang immer noch fehlschlägt, können Sie die Anzahl der Wiederholungsversuche erhöhen, aber diese Anzahl muss begrenzt werden. Wenn sie eine bestimmte Anzahl überschreitet, müssen Maßnahmen wie das Melden von Fehlern, das Aufzeichnen von Protokollen und das Versenden von E-Mail-Erinnerungen ergriffen werden.
  2. 5. Verwenden Sie die Nachrichtenwarteschlange, um das Löschen zu kompensieren.
  3. Zuerst die Datenbank aktualisieren und dann den Cache löschen. Diese Situation führt beispielsweise auch zu Problemen, wenn die Datenbank erfolgreich aktualisiert wird, während der Cache-Löschphase jedoch ein Fehler auftritt Wenn der Löschvorgang nicht erfolgreich ist, sind die Daten zu diesem Zeitpunkt beim erneuten Lesen des Caches jedes Mal falsch.
  4. Die Lösung besteht derzeit darin, die Nachrichtenwarteschlange zu verwenden, um das Löschen zu kompensieren. Die spezifische Geschäftslogiksprache wird wie folgt beschrieben:

Fordern Sie Thread A auf, die Datenbank zu aktualisieren.

Beim Löschen von Redis wurde ein Fehler gemeldet, und der Löschvorgang ist fehlgeschlagen.

Zu diesem Zeitpunkt wird der Schlüssel von Redis verwendet Der Nachrichtentext wird an die Nachrichtenwarteschlange gesendet.

Nachdem das System die von der Nachrichtenwarteschlange gesendete Nachricht empfangen hat, löscht es Redis erneut.

Diese Lösung hat jedoch den Nachteil, dass sie viele Eingriffe verursacht In den Geschäftscode eingebunden, wird es zu diesem Zeitpunkt eine Optimierungsmethode geben. Wir wissen, dass wir nach der Aktualisierung der MySQL-Datenbank die entsprechenden Vorgänge im Binlog-Protokoll finden können Binlog-Protokoll der MySQL-Datenbank zum Betreiben des Caches.
So stellen Sie die Konsistenz zwischen Redis-Cache und Datenbank sicherEmpfohlenes Lernen:

Redis-Tutorial

Das obige ist der detaillierte Inhalt vonSo stellen Sie die Konsistenz zwischen Redis-Cache und Datenbank sicher. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen