Heim > Datenbank > MySQL-Tutorial > Hauptteil

Was soll ich tun, wenn die Double-Write-Caches von Redis und MySQL inkonsistent sind? Lösungsaustausch

青灯夜游
Freigeben: 2022-03-15 11:20:18
nach vorne
2419 Leute haben es durchsucht

Was soll ich tun, wenn der Double-Write-Cache von Redis und MySQL inkonsistent ist? In diesem Artikel erfahren Sie, wie Sie das Problem der Inkonsistenz beim doppelten Schreiben im Cache lösen können.

Was soll ich tun, wenn die Double-Write-Caches von Redis und MySQL inkonsistent sind? Lösungsaustausch

Redis und MySQL Double-Write-Cache sind inkonsistent:

Was soll ich tun, wenn die Double-Write-Caches von Redis und MySQL inkonsistent sind? Lösungsaustausch

Aber in Bezug auf die Aktualisierung des Caches gibt es derzeit keinen umfassenden Blog, der diese Lösungen analysiert. Also schrieb der Blogger diesen Artikel zitternd und riskierte, von allen kritisiert zu werden. 更新完数据库,是更新缓存呢,还是删除缓存。又或者是先删除缓存,再更新数据库,其实大家存在很大的争议。

Text

Ablaufzeit für zwischengespeicherte Daten festlegen

Lassen Sie mich zunächst erklären, dass das Festlegen der Ablaufzeit für den Cache eine Lösung ist, um letztendlich Konsistenz sicherzustellen. Bei dieser Lösung können wir die Ablaufzeit für die im Cache gespeicherten Daten festlegen. Alle Schreibvorgänge unterliegen der Datenbank und wir müssen nur für Cache-Vorgänge unser Bestes geben. Das heißt, wenn das Schreiben in die Datenbank erfolgreich ist und die Cache-Aktualisierung fehlschlägt, lesen nachfolgende Leseanforderungen natürlich neue Werte aus der Datenbank und füllen den Cache auf, solange die Ablaufzeit erreicht ist. Daher basieren die im Folgenden besprochenen Ideen nicht auf der Lösung, eine Ablaufzeit für den Cache festzulegen.

Hier besprechen wir zunächst drei

Update-Strategien:

    Zuerst die Datenbank aktualisieren, dann den Cache aktualisieren
  1. Zuerst den Cache löschen, dann die Datenbank aktualisieren
  2. Zuerst die Datenbank aktualisieren und dann den Cache löschen
Aktualisieren Sie zuerst die Datenbank und dann den Cache.

Dieser Plan wird im Allgemeinen von allen abgelehnt. Warum? Es gibt die folgenden zwei Punkte:

    Grund eins (Thread-Sicherheitsperspektive)
(1) Thread A hat die Datenbank aktualisiert

(2) Thread B hat die Datenbank aktualisiert
(3) Thread B hat den Cache aktualisiert
(4) Thread A hat den Cache aktualisiert

Das bedeutet, dass die Aufforderung an A, den Cache zu aktualisieren, früher erfolgen sollte als die Aufforderung an B, den Cache zu aktualisieren. Aus Netzwerk- und anderen Gründen hat B den Cache jedoch früher aktualisiert als A. Dies führt zu fehlerhaften Daten und wird daher nicht berücksichtigt.

    Grund zwei (Geschäftsszenario-Perspektive)
(1) Wenn Sie geschäftliche Anforderungen mit mehr Datenbankschreibszenarien und weniger Datenleseszenarien haben, führt die Übernahme dieser Lösung dazu, dass die Daten überhaupt nicht gelesen werden häufig aktualisiert, was zu Leistungseinbußen führt.

(2) Wenn der Wert, den Sie in die Datenbank schreiben, nicht direkt in den Cache geschrieben wird, muss er eine Reihe komplexer Berechnungen durchlaufen und dann in den Cache geschrieben werden. Dann ist es zweifellos eine Leistungsverschwendung, den in den Cache geschriebenen Wert jedes Mal neu zu berechnen, wenn er in die Datenbank geschrieben wird. Offensichtlich ist das Löschen des Caches sinnvoller.

Löschen Sie zuerst den Cache und aktualisieren Sie dann die Datenbank

Der Grund, warum diese Lösung zu Inkonsistenzen führt, ist. Gleichzeitig fordert einer von A eine Aktualisierungsoperation und der andere von B eine Abfrageoperation an. Dann tritt die folgende Situation ein:

(1) Fordern Sie A auf, einen Schreibvorgang durchzuführen und den Cache zu löschen.

(2) Fordern Sie B auf, eine Abfrage durchzuführen und festzustellen, dass der Cache nicht vorhanden ist.
(3) Fordern Sie B auf, die Datenbank abzufragen Holen Sie sich den alten Wert
(4) Fordern Sie B an, den alten Wert abzurufen. Der Wert wird in den Cache geschrieben.
(5) Fordern Sie A an, den neuen Wert in die Datenbank zu schreiben. Die obige Situation führt zu Inkonsistenzen. Wenn Sie außerdem keine Ablaufzeitstrategie für den Cache festlegen, handelt es sich bei den Daten immer um fehlerhafte Daten.

Also, wie kann man es lösen? Übernehmen Sie die Strategie des verzögerten doppelten Löschens

Cache-verzögertes doppeltes Löschen

public class CacheServiceImpl implements ICacheService {

    @Resource
    private RedisOperator redisOperator;
    
    @Autowired
    private IShopService shopService;

    //1. 采用延时双删,解决数据库和缓存的一致性
    @Override
    public void updateHotCount(String id) {
        try {
            //删除缓存
            redisOperator.del("redis_key_" + id);
            //更新数据库
            shopService.updataHotShop();
            Thread.sleep(1000);//休眠1秒
            //延时删除
            redisOperator.del("redis_key_" + id);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


    }

    @Override
    public Integer getHotCount(String id) {
        return null;
    }}
Nach dem Login kopieren
Erklärung:

Löschen Sie zuerst den Cache

    Schreiben Sie dann in die Datenbank
  1. Eine Sekunde lang schlafen und dann den Cache löschen (
  2. Auf diese Weise , Sie können 1 Sekunde verkürzen. Die durch den Cache verursachten zwischengespeicherten schmutzigen Daten werden erneut gelöscht. Dann basiert die Ruhezeit zum Schreiben von Daten auf der Zeit, die die Geschäftslogik zum Lesen von Daten benötigt, plus einigen hundert Millisekunden. Der Zweck besteht darin, sicherzustellen, dass die Leseanforderung endet und die Schreibanforderung die durch die Leseanforderung verursachten zwischengespeicherten schmutzigen Daten löschen kann.
  3. Was passiert, wenn die Datenbank eine Lese-/Schreib-Trennarchitektur übernimmt?
  4. (
Die Hauptbibliothek ist für den Schreibvorgang verantwortlich und die Slave-Bibliothek ist für den Lesevorgang verantwortlich

)OK, in diesem Fall ist der Grund für die Dateninkonsistenz wie folgt. Es gibt immer noch zwei Anfragen, eine fordert A an um den Aktualisierungsvorgang durchzuführen, und der andere fordert B auf, den Aktualisierungsvorgang auszuführen. (1) Fordern Sie A auf, einen Schreibvorgang durchzuführen, den Cache zu löschen, fordern Sie A auf, Daten in die Hauptbibliothek zu schreiben, und haben Sie noch nicht mit der Synchronisierung der Slave-Bibliothek begonnen.

(2) (innerhalb von 1 s) fordern Sie B auf, die abzufragen Cache, aber kein Cache gefunden, Anforderung B zum Gehen Bei der Abfrage aus der Datenbank ist die Master-Slave-Synchronisation noch nicht abgeschlossen. Der alte Wert wird gefunden und der alte Wert wird in den Cache geschrieben. (3) Die Master-Datenbank schließt die Master-Slave-Synchronisation ab und die Slave-Datenbank ändert sich auf den neuen WertDer obige Prozess ist das Problem der Dateninkonsistenz, und es wird auch eine Strategie zur Verzögerung der doppelten Löschung verwendet. Die Ruhezeit wird jedoch so geändert, dass sie auf der Master-Slave-Synchronisationsverzögerungszeit plus ein paar hundert ms basiert

Was soll ich tun, wenn diese Synchronisationseliminierungsstrategie übernommen wird, wenn der Durchsatz reduziert wird?

ok, dann führen Sie den zweiten Löschvorgang asynchron durch. Starten Sie selbst einen Thread und löschen Sie ihn asynchron. Auf diese Weise muss die schriftliche Anfrage nicht eine Zeit lang ruhen, bevor sie zurückgesendet wird. Dadurch wird der Durchsatz erhöht.

Zweite Löschung, was soll ich tun, wenn die Löschung fehlschlägt?

Das ist eine sehr gute Frage, denn wenn der Löschvorgang zum zweiten Mal fehlschlägt, kommt es zu folgender Situation. Es gibt noch zwei Anfragen, eine fordert A auf, eine Aktualisierungsoperation durchzuführen, und die andere fordert B auf, eine Abfrageoperation durchzuführen. Der Einfachheit halber wird davon ausgegangen, dass es sich um eine einzelne Datenbank handelt:

(1) Fordern Sie A auf, eine Schreiboperation durchzuführen und den Cache löschen
(2) Fordern Sie B auf, den Cache abzufragen und zu entdecken. Der Cache existiert nicht
(3) Fordern Sie B auf, die Datenbank abzufragen, um den alten Wert zu erhalten
(4) Fordern Sie B auf, den alten Wert in den Cache zu schreiben
( 5) Anforderung A, den neuen Wert in die Datenbank zu schreiben
(6) Anforderung A versucht, Anforderung B zu löschen. Das Schreiben in den zwischengespeicherten Wert ist fehlgeschlagen.

ok, das heißt. Wenn das Löschen des Caches zum zweiten Mal fehlschlägt, tritt die Inkonsistenz zwischen Cache und Datenbank erneut auf.

Wie kann man es lösen?

Für die spezifische Lösung schauen wir uns die Analyse des Bloggers zur Aktualisierungsstrategie an, bei der zuerst die Datenbank aktualisiert und dann der Cache gelöscht wird.

Cache-Wiederholungsmechanismus löschen

Ob es sich um eine verzögerte doppelte Löschung oder einen Cache-Aside-Mechanismus handelt, der zuerst die Datenbank betreibt und dann den Cache löscht, kann es zu Dateninkonsistenzproblemen kommen, die dadurch verursacht werden, dass der Cache im nicht gelöscht wird zweiter Schritt. Sie können diese Lösung zur Optimierung verwenden: Wenn der Löschvorgang fehlschlägt, löschen Sie ihn noch einige Male, um sicherzustellen, dass der Cache-Löschvorgang erfolgreich ist. ~ So können Sie den Lösch-Cache-Wiederholungsmechanismus

Was soll ich tun, wenn die Double-Write-Caches von Redis und MySQL inkonsistent sind? Lösungsaustausch

  1. einführen (1) Datenbank aktualisieren Daten;
    (2) Der Cache konnte aufgrund verschiedener Probleme nicht gelöscht werden
    (3) Senden Sie den zu löschenden Schlüssel an die Nachrichtenwarteschlange
    (4) Verarbeiten Sie die Nachricht selbst und erhalten Sie den zu löschenden Schlüssel
    (5) Wiederholen Sie den Löschvorgang so lange, bis er erfolgreich ist

Diese Lösung hat jedoch den Nachteil, dass sie viele Eingriffe in den Branchencode verursacht. Wir haben also die zweite Option: Starten Sie ein Abonnementprogramm, um das Binlog der Datenbank zu abonnieren und die Daten zu erhalten, die bearbeitet werden müssen. Starten Sie in der Anwendung ein neues Programm, um die Informationen aus diesem Abonnementprogramm abzurufen und den Cache zu löschen.

Biglog lesen und Cache asynchron löschen

Was soll ich tun, wenn die Double-Write-Caches von Redis und MySQL inkonsistent sind? Lösungsaustausch

Der Vorgang ist wie in der folgenden Abbildung dargestellt:

(1) Datenbankdaten aktualisieren
(2) Die Datenbank schreibt die Vorgangsinformationen in das Binlog-Protokoll
( 3) Abonnentenextraktion Herausnehmen der erforderlichen Daten und des Schlüssels
(4) Starten Sie einen neuen nicht geschäftlichen Code, um die Informationen zu erhalten
(5) Versuchen Sie, den Cache-Vorgang zu löschen und stellen Sie fest, dass der Löschvorgang fehlgeschlagen ist
(6) Senden Sie die Informationen zur Nachrichtenwarteschlange
(7) Empfangen Sie die Nachricht erneut. Erhalten Sie die Daten in der Warteschlange und wiederholen Sie den Vorgang.

Bemerkungen: Das obige Binlog-Abonnementprogramm verfügt über eine vorgefertigte Middleware namens Canal in MySQL, die die Funktion des Abonnierens von Binlog-Protokollen vervollständigen kann. Was Oracle betrifft, weiß der Blogger derzeit nicht, ob es bereits fertige Middleware gibt, die genutzt werden kann. Darüber hinaus verwendet der Blogger für den Wiederholungsmechanismus eine Nachrichtenwarteschlange. Wenn die Konsistenzanforderungen nicht sehr hoch sind, starten Sie einfach einen neuen Thread im Programm und versuchen Sie es von Zeit zu Zeit erneut. Sie können dies flexibel verwenden, aber ich gebe nur eine Idee.

Dieser Artikel ist eigentlich eine Zusammenfassung der vorhandenen Konsistenzlösungen im Internet. In Bezug auf die Aktualisierungsstrategie, bei der zuerst der Cache gelöscht und dann die Datenbank aktualisiert wird, ist auch die Aufrechterhaltung einer Speicherwarteschlange geplant. Der Blogger hat sich das angesehen und festgestellt, dass die Implementierung äußerst kompliziert und unnötig ist und daher nicht angegeben werden muss im Artikel. Abschließend hoffe ich, dass Sie alle etwas gewonnen haben.

【Verwandte Empfehlung: MySQL-Video-Tutorial

Das obige ist der detaillierte Inhalt vonWas soll ich tun, wenn die Double-Write-Caches von Redis und MySQL inkonsistent sind? Lösungsaustausch. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:jianshu.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage