Que dois-je faire si le cache en double écriture de Redis et MySQL est incohérent ? Cet article vous expliquera comment résoudre le problème d'incohérence de double écriture du cache. J'espère qu'il pourra vous aider !
redis et le cache à double écriture mysql sont incohérents :
Mais en termes de mise à jour du cache, il n'existe actuellement aucun blog complet qui analyse ces solutions. Le blogueur a donc écrit cet article en tremblant et au risque d'être critiqué par tout le monde. 更新完数据库,是更新缓存呢,还是删除缓存。
又或者是先删除缓存,再更新数据库,其实大家存在很大的争议。
Définir le délai d'expiration pour les données mises en cache
Laissez-moi d'abord vous expliquer En théorie, définir le délai d'expiration du cache est une solution pour garantir une cohérence éventuelle. Avec cette solution, nous pouvons définir le délai d'expiration des données stockées dans le cache. Toutes les opérations d'écriture sont soumises à la base de données, et nous devons uniquement faire de notre mieux pour les opérations de cache. C'est-à-dire que si l'écriture de la base de données réussit et que la mise à jour du cache échoue, tant que le délai d'expiration est atteint, les demandes de lecture ultérieures liront naturellement les nouvelles valeurs de la base de données et rempliront le cache. Par conséquent, les idées discutées ci-dessous ne reposent pas sur la solution consistant à définir un délai d’expiration pour le cache. Ici, nous discutons d'abord de troisstratégies de mise à jour :
Mettez d'abord à jour la base de données, puis mettez à jour le cacheCe plan est généralement opposé par tout le monde. Pourquoi? Il y a les deux points suivants :
(2) Le fil B a mis à jour la base de données
(3) Le fil B a mis à jour le cache
(4) Discussion A Cache mis à jour
Supprimez d'abord le cache, puis mettez à jour la base de donnéesLa raison pour laquelle cette solution provoquera une incohérence est la suivante. En même temps, l'un demande à A d'effectuer une opération de mise à jour et l'autre demande à B d'effectuer une opération de requête. Ensuite, la situation suivante se produira : (1) Demande à A d'effectuer une opération d'écriture et de suppression du cache
(2) Demande à B d'interroger et de constater que le cache n'existe pas
(3) Demande à B d'interroger la base de données pour récupérer l'ancienne valeur
(4) Demande à B de récupérer l'ancienne valeur La valeur est écrite dans le cache
(5) Demande à A d'écrire la nouvelle valeur dans la base de données
Alors, comment le résoudre ? Adopter une stratégie de double suppression retardée
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; }}
Compte tenu de la situation ci-dessus, les lecteurs devraient évaluer la logique métier fastidieuse de lecture des données de leurs propres projets. Ensuite, le temps de veille pour l'écriture des données est basé sur le temps nécessaire à la logique métier pour lire les données, plus quelques centaines de millisecondes. Le but de ceci est de garantir que la demande de lecture se termine et que la demande d'écriture peut supprimer les données sales mises en cache causées par la demande de lecture.
Et si la base de données adoptait une architecture de séparation lecture-écriture ? (La bibliothèque principale est responsable des opérations d'écriture et la bibliothèque esclave est responsable des opérations de lecture)
ok, dans ce cas, la raison de l'incohérence des données est la suivante. Il y a encore deux requêtes, une demandant A. pour effectuer l'opération de mise à jour, et l'autre demandant à B d'effectuer l'opération de mise à jour. (1) Demander à A d'effectuer une opération d'écriture, supprimer le cache, demander à A d'écrire des données dans la bibliothèque principale et n'avoir pas encore commencé à synchroniser la bibliothèque esclave (2) (dans les 1 secondes) demander à B d'interroger le cache, mais aucun cache n'est trouvé, demandez à B d'y aller Lors de l'interrogation à partir de la base de données, la synchronisation maître-esclave n'est pas encore terminée, l'ancienne valeur est trouvée et l'ancienne valeur est écrite dans le cache. (3) La base de données maître termine la synchronisation maître-esclave et la base de données esclave passe à la nouvelle valeurLe processus ci-dessus est le problème de l'incohérence des données, et une stratégie de délai de double suppression est également utilisée. Cependant, le temps de veille est modifié pour être basé sur le délai de synchronisation maître-esclave, plus quelques centaines de msSi cette stratégie d'élimination de synchronisation est adoptée, que dois-je faire si le débit est réduit ?
ok, alors rendez la deuxième suppression asynchrone. Démarrez vous-même un fil de discussion et supprimez-le de manière asynchrone. De cette façon, la demande écrite n'a pas besoin de dormir pendant un certain temps avant de revenir. Cela augmente le débit.
Suppression pour la deuxième fois, que dois-je faire si la suppression échoue ?
C'est une très bonne question, car si la suppression échoue une deuxième fois, la situation suivante se produira. Il existe toujours deux requêtes, l'une demande à A d'effectuer une opération de mise à jour et l'autre demande à B d'effectuer une opération de requête. Pour plus de commodité, il s'agit d'une seule base de données :
(1) Demande à A d'effectuer une opération d'écriture. et supprimez le cache
(2) Demande à B d'interroger et de découvrir Le cache n'existe pas
(3) Demande à B d'interroger la base de données pour obtenir l'ancienne valeur
(4) Demande à B d'écrire l'ancienne valeur dans le cache
( 5) Demande A pour écrire la nouvelle valeur dans la base de données
(6) La demande A tente de supprimer la demande B L'écriture dans la valeur mise en cache a échoué.
ok, c'est pour dire. Si la suppression du cache échoue une deuxième fois, l'incohérence du cache et de la base de données se reproduira.
Comment le résoudre ?
Pour la solution spécifique, regardons l'analyse du blogueur de la stratégie de mise à jour consistant à mettre à jour d'abord la base de données, puis à supprimer le cache.
Qu'il s'agisse d'une double suppression retardée ou d'un Cache-Aside qui exploite d'abord la base de données puis supprime le cache, il peut y avoir des problèmes d'incohérence des données causés par l'échec de la suppression du cache dans le deuxième étape. Vous pouvez utiliser cette solution pour optimiser : si la suppression échoue, supprimez-la encore quelques fois pour vous assurer que la suppression du cache est réussie~ Vous pouvez ainsi introduire le mécanisme de nouvelle tentative de suppression du cache
Cependant, cette solution présente l'inconvénient de provoquer de nombreuses intrusions dans le code métier. Nous avons donc la deuxième option. Dans la deuxième option, démarrez un programme d'abonnement pour vous abonner au binlog de la base de données afin d'obtenir les données à exploiter. Dans l'application, démarrez un nouveau programme pour obtenir les informations de ce programme d'abonnement et supprimez le cache.
Le processus est comme indiqué dans la figure ci-dessous :
(1) Mettre à jour les données de la base de données
(2) La base de données écrira les informations sur l'opération dans le journal binlog
( 3) Extraction de l'abonné Extrayez les données et la clé requises
(4) Démarrez un nouveau morceau de code non commercial pour obtenir les informations
(5) Essayez de supprimer l'opération de cache et constatez que la suppression a échoué
(6) Envoyez les informations à la file d'attente des messages
(7) Recevez à nouveau le message Obtenez les données dans la file d'attente et réessayez l'opération.
Remarques : Le programme d'abonnement au binlog ci-dessus dispose d'un middleware prêt à l'emploi appelé canal dans MySQL, qui peut compléter la fonction d'abonnement aux journaux binlog. Quant à Oracle, le blogueur ne sait pas actuellement s'il existe un middleware prêt à l'emploi pouvant être utilisé. De plus, comme pour le mécanisme de nouvelle tentative, le blogueur utilise une file d'attente de messages. Si les exigences de cohérence ne sont pas très élevées, démarrez simplement un nouveau thread dans le programme et réessayez de temps en temps. Vous pouvez l'utiliser de manière flexible, mais je donne juste une idée.
Cet article est en fait une synthèse des solutions de cohérence existantes sur Internet. Concernant la stratégie de mise à jour consistant à supprimer d'abord le cache puis à mettre à jour la base de données, il existe également un plan pour maintenir une file d'attente mémoire. Le blogueur l'a examiné et a estimé que la mise en œuvre est extrêmement compliquée et inutile, il n'est donc pas nécessaire de la donner. dans l'article. Enfin, j'espère que vous avez tous gagné quelque chose.
【Recommandation associée : tutoriel vidéo mysql】
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!