Maison >base de données >Redis >Comment assurer la cohérence entre le cache Redis et la base de données

Comment assurer la cohérence entre le cache Redis et la base de données

WBOY
WBOYavant
2022-03-17 18:50:153170parcourir

Cet article vous apporte des connaissances pertinentes sur Redis Il présente principalement les problèmes liés à la façon d'assurer la cohérence du cache Redis et de la base de données, y compris la mise à jour du cache et la mise à jour de la base de données, etc. .

Comment assurer la cohérence entre le cache Redis et la base de données

Apprentissage recommandé : Tutoriel d'apprentissage Redis

1. Quatre stratégies de synchronisation :

Pour garantir la double écriture du cache et de la base de données, il existe 4 manières, soit 4 stratégies de synchronisation :

    .
  1. Mettez d'abord à jour le cache, puis mettez à jour la base de données ;
  2. Mettez d'abord à jour la base de données, puis mettez à jour le cache ;
  3. Supprimez d'abord le cache, puis mettez à jour la base de données ;
  4. Mettez d'abord à jour la base de données, puis supprimez le cache.

Parmi ces 4 stratégies de synchronisation, ce que nous devons comparer est :

Quelle méthode est la plus adaptée pour mettre à jour le cache ou supprimer le cache ? La base de données doit-elle être exploitée en premier ou le cache en premier ?

2. Mettre à jour le cache ou supprimer le cache

Ensuite, analysons si nous devons mettre à jour le cache ou supprimer le cache.

2.1 Mettre à jour le cache

Avantages :Le cache est mis à jour à temps à chaque fois que les données changent, de sorte que des échecs sont moins susceptibles de se produire lors des requêtes.

Inconvénients : La mise à jour du cache est relativement coûteuse. Si les données doivent subir des calculs complexes avant d'être écrites dans le cache, les mises à jour fréquentes du cache affecteront les performances du serveur. S'il s'agit d'un scénario commercial dans lequel les données sont écrites fréquemment, il se peut qu'aucune entreprise ne lise les données lorsque le cache est fréquemment mis à jour.

2.2 Supprimer le cache

Avantages :Opération simple, que l'opération de mise à jour soit compliquée ou non, les données du cache seront directement supprimées.

Inconvénients : Après la suppression du cache, le prochain cache de requêtes manquera et la base de données devra être relue. D’après la comparaison ci-dessus, en général, la suppression du cache est une meilleure solution.

3. La base de données ou le cache doivent-ils être exploités en premier ? Ensuite, analysons si la base de données ou le cache doivent être exploités en premier.

Tout d'abord, nous allons d'abord supprimer le cache et mettre à jour la base de données, puis faire une comparaison en cas d'échec :


3.1 Supprimez d'abord le cache, puis mettez à jour la base de données出现失败时进行一个对比:

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

Comment assurer la cohérence entre le cache Redis et la base de données
如上图,是先删除缓存再更新数据库,在出现失败时可能出现的问题:

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

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

Comment assurer la cohérence entre le cache Redis et la base de données
如上图,是先更新数据库再删除缓存,在出现失败时可能出现的问题:

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

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

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




下面我们再将先删缓存与先更新数据库,在没有出现失败时进行对比:
Comment assurer la cohérence entre le cache Redis et la base de données
如上图,是先删除缓存再更新数据库,在没有出现失败时

Veuillez ajouter une description d'image🎜 Comme indiqué ci-dessus, le cache est d'abord supprimé, puis la base de données est supprimée. mis à jour. Problèmes pouvant survenir en cas d'échec :🎜
    🎜Le thread A supprime le cache avec succès, mais le thread A ne parvient pas à mettre à jour la base de données ; 🎜🎜Le thread B lit les données du cache car le cache est supprimé, processus ; B ne peut pas obtenir les données du cache, puis lit les données de la base de données ; à ce moment, la mise à jour des données dans la base de données a échoué. 🎜🎜🎜Au final, les données du cache et de la base de données sont cohérentes, mais ce sont toujours des données anciennes🎜🎜
🎜3.2 Mettez d'abord à jour la base de données puis supprimez le cache🎜🎜Veuillez ajouter une description d'image🎜 Comme indiqué ci-dessus, la base de données est d'abord mise à jour, puis le cache est supprimé. Lorsque un échec se produit Problèmes possibles : 🎜
    🎜Le thread A met à jour la base de données avec succès, mais le thread A ne parvient pas à supprimer le cache ; 🎜🎜Le thread B lit le cache avec succès, mais comme la suppression du cache échoue, le thread B lit les anciennes données dans le cache. 🎜🎜Enfin, le thread A a supprimé avec succès le cache et d'autres threads ont accédé aux mêmes données dans le cache, qui sont les mêmes que les données de la base de données. 🎜🎜🎜Finalement, les données du cache et de la base de données sont cohérentes, mais certains threads liront les anciennes données. 🎜🎜
🎜Après la comparaison ci-dessus, nous avons constaté que lorsque échoue, il est impossible de distinguer clairement quelle méthode est la meilleure : supprimer d'abord le cache ou mettre à jour la base de données d'abord, pensant que les deux eux ont des problèmes. Nous comparerons plus en détail ces deux méthodes plus tard, mais nous discutons ici d'abord de la manière de résoudre les problèmes qui surviennent dans les scénarios ci-dessus ? 🎜🎜En fait, quelle que soit la méthode que nous utilisons ci-dessus pour synchroniser le cache et la base de données, lorsque la deuxième étape échoue, il est recommandé d'utiliser un mécanisme de nouvelle tentative, qui a été dessiné dans les deux images au-dessus de . 🎜


🎜Comparons maintenant d'abord la suppression du cache et la mise à jour de la base de données, et quand il n'y a pas d'échec pour comparer : 🎜Veuillez ajouter une description d'image🎜 Comme indiqué ci-dessus, le cache est d'abord supprimé, puis la base de données est mis à jour. Il n'y a pas de Problèmes possibles en cas de panne : 🎜<ul> <li>Le thread A a supprimé le cache avec succès ; </li> <li>Le thread B n'a pas réussi à lire le cache ; </li> <li>Le thread B a réussi à lire la base de données et a récupéré les anciennes données ; </li> <li>Le thread B a réussi à mettre à jour les anciennes données dans le cache ; will Les nouvelles données sont mises à jour avec succès dans la base de données. </li> <li>On peut voir que les deux étapes du processus A ont réussi, mais en raison de la concurrence, le processus B a accédé au cache entre les deux étapes. </ul>Le résultat final est que les anciennes données sont stockées dans le cache et les nouvelles données sont stockées dans la base de données, et les deux données sont incohérentes. <p><strong></strong></p> <hr> <hr> <p> Comme le montre l'image ci-dessus, la base de données est d'abord mise à jour, puis le cache est supprimé. Problèmes possibles dans <img src="https://img.php.cn/upload/article/000/000/067/e73f1a06231a665bb67debaa27b6baf0-3.png" alt="Comment assurer la cohérence entre le cache Redis et la base de données"> : <br><code>没有出现失败时

Le thread A a mis à jour la base de données avec succès ;
  • Le thread B a lu le cache avec succès ;
  • Thread A a supprimé le cache avec succès.
  • On peut voir que
le cache final est cohérent avec les données de la base de données, et les deux sont les dernières données

. Mais le thread B lit les anciennes données pendant ce processus. Il peut y avoir d'autres threads comme le thread B qui lisent les anciennes données dans le cache entre ces deux étapes, mais comme la vitesse d'exécution de ces deux étapes sera plus rapide, l'impact n'est donc pas important. grand. Après ces deux étapes, lorsque d’autres processus liront les données mises en cache, des problèmes similaires à ceux du processus B ne se produiront plus. Conclusion finale :

Après comparaison, vous constaterez que mettre à jour d'abord la base de données puis supprimer le cache est une solution avec moins d'impact. Si la deuxième étape échoue, un mécanisme de nouvelle tentative peut être utilisé pour résoudre le problème.

4. Double suppression retardée

Nous avons mentionné ci-dessus que

si le cache est d'abord supprimé puis la base de données est mise à jour, cela peut entraîner une incohérence des données même s'il n'y a pas d'échec. Si dans des applications réelles, nous devons choisir cette méthode en raison de certaines considérations, existe-t-il un moyen de résoudre ce problème ? La réponse est oui, c'est-à-dire adopter la stratégie de double suppression retardée. L'idée de base de double suppression retardée est la suivante :

supprimer le cache
  1. mettre à jour la base de données ;
  2. supprimez à nouveau le cache.
  3. 	public void write(String key, Object data) {
            Redis.delKey(key);
            db.updateData(data);
            Thread.sleep(1000);
            Redis.delKey(key);
        }
  4. Après le blocage pendant un certain temps, supprimez à nouveau le cache pour supprimer les données incohérentes dans le cache pendant ce processus
  5. . Quant à l'heure précise, vous devez évaluer l'heure approximative de votre entreprise et la régler en fonction de cette heure.

4.1 Que faire si l'architecture sépare la lecture et l'écriture ? Si la base de données adopte une architecture de séparation lecture-écriture, alors de nouveaux problèmes surgiront, comme indiqué ci-dessous :

A ce moment, deux requêtes sont arrivées, la requête A (opération de mise à jour) et la requête B (opération de requête)


Comment assurer la cohérence entre le cache Redis et la base de données Demander à A d'effectuer une opération de mise à jour et de supprimer Redis ;

Demander à la bibliothèque principale d'effectuer une opération de mise à jour, et à la bibliothèque principale et à la bibliothèque esclave de synchroniser les données 
  1. Demander à B d'effectuer une opération de requête et de constater qu'il n'y a pas de données ; données dans Redis ;
  2. Allez à la bibliothèque esclave Récupérez les données ;
  3. La synchronisation des données n'est pas terminée pour le moment et les données obtenues sont d'anciennes données
  4. La solution pour le moment est d'interroger la base de données ; remplir les données dans Redis, puis forcer à pointer vers la bibliothèque principale pour la requête.
Que dois-je faire si la suppression échoue ?

Si la suppression échoue toujours, vous pouvez augmenter le nombre de tentatives, mais ce nombre doit être limité. Lorsqu'il dépasse un certain nombre, des mesures telles que le signalement des erreurs, l'enregistrement des journaux et l'envoi de rappels par e-mail doivent être prises. 5. Utilisez la file d'attente des messages pour compenser la suppression

Mettez d'abord à jour la base de données, puis supprimez le cache

Cette situation entraînera également des problèmes. Par exemple, la base de données est mise à jour avec succès, mais une erreur se produit lors de l'étape de suppression du cache et. la suppression n'a pas réussi. Ensuite, à ce moment-là, lors de la nouvelle lecture du cache, les données seront erronées à chaque fois.

La solution pour le moment est d'utiliser la file d'attente des messages pour compenser la suppression. Le langage de logique métier spécifique est décrit comme suit :
Comment assurer la cohérence entre le cache Redis et la base de données

Demander au thread A de mettre à jour la base de données en premier ;

Une erreur a été signalée lors de la suppression de Redis, et la suppression a échoué
  1. À ce stade, la clé de Redis est utilisée comme ; le corps du message Envoyer à la file d'attente des messages ;
  2. Une fois que le système a reçu le message envoyé par la file d'attente des messages, il supprime à nouveau Redis
  3. Cependant, cette solution aura un inconvénient, c'est qu'elle provoquera beaucoup d'intrusions ; dans le code métier, et il sera profondément couplé. Ensemble, il y aura une méthode d'optimisation à ce moment-là. Nous savons qu'après la mise à jour de la base de données Mysql, nous pourrons retrouver les opérations correspondantes dans le journal binlog. journal binlog de la base de données Mysql pour faire fonctionner le cache.

Apprentissage recommandé :
Tutoriel RedisComment assurer la cohérence entre le cache Redis et la base de données

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer