Maison >base de données >tutoriel mysql >Que dois-je faire si les caches à double écriture de Redis et MySQL sont incohérents ? Partage de solutions

Que dois-je faire si les caches à double écriture de Redis et MySQL sont incohérents ? Partage de solutions

青灯夜游
青灯夜游avant
2022-03-15 11:18:292446parcourir

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 !

Que dois-je faire si les caches à double écriture de Redis et MySQL sont incohérents ? Partage de solutions

redis et le cache à double écriture mysql sont incohérents :

Que dois-je faire si les caches à double écriture de Redis et MySQL sont incohérents ? Partage de solutions

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. 更新完数据库,是更新缓存呢,还是删除缓存。又或者是先删除缓存,再更新数据库,其实大家存在很大的争议。

Texte

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 trois

stratégies de mise à jour :

    Mettre à jour d'abord la base de données, puis mettre à jour le cache
  1. Supprimer d'abord le cache, puis mettre à jour la base de données
  2. Mettre à jour d'abord la base de données, puis supprimer le cache
Mettez d'abord à jour la base de données, puis mettez à jour le cache

Ce plan est généralement opposé par tout le monde. Pourquoi? Il y a les deux points suivants :

    Première raison (perspective de la sécurité des threads)
(1) Le fil A a mis à jour la base de données

(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

Cela signifie que demander à A de mettre à jour le cache devrait être plus tôt que de demander à B de mettre à jour le cache. Cependant, en raison du réseau et d'autres raisons, B a mis à jour le cache plus tôt que A. Cela entraîne des données sales et n'est donc pas pris en compte.

    Raison deux (perspective du scénario commercial)
(1) Si vous avez des besoins professionnels avec plus de scénarios d'écriture de base de données et moins de scénarios de lecture de données, l'adoption de cette solution entraînera la non-lecture des données, le cache l'est. mis à jour fréquemment, ce qui gaspille les performances.

(2) Si la valeur que vous écrivez dans la base de données n'est pas écrite directement dans le cache, elle doit passer par une série de calculs complexes puis être écrite dans le cache. Ensuite, calculer à nouveau la valeur écrite dans le cache à chaque fois qu'elle est écrite dans la base de données est sans aucun doute un gaspillage de performances. Évidemment, la suppression du cache est plus appropriée.

Supprimez d'abord le cache, puis mettez à jour la base de données

La 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

La situation ci-dessus entraînera des incohérences. De plus, si vous ne définissez pas de stratégie de délai d’expiration pour le cache, les données seront toujours des données sales.

Alors, comment le résoudre ? Adopter une stratégie de double suppression retardée

Double suppression retardée du cache
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;
    }}

Explication :

    Éliminez d'abord le cache
  1. puis écrivez dans la base de données
  2. Veillez 1 seconde, puis éliminez le cache (
  3. De cette façon , vous pouvez réduire 1 seconde à Les données sales mises en cache causées par le problème seront à nouveau supprimées )

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 valeur

Le 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 ms

Si 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.

Mécanisme de nouvelle tentative de suppression du 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

Que dois-je faire si les caches à double écriture de Redis et MySQL sont incohérents ? Partage de solutions

  1. (1) Mettre à jour la base de données données ;
    (2) La suppression du cache n'a pas pu être effectuée en raison de divers problèmes
    (3) Envoyez la clé qui doit être supprimée à la file d'attente des messages
    (4) Consommez le message vous-même et obtenez la clé qui doit être supprimée
    (5) Continuez à réessayer l'opération de suppression jusqu'à ce qu'elle réussisse

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.

Lire le biglog et supprimer le cache de manière asynchrone

Que dois-je faire si les caches à double écriture de Redis et MySQL sont incohérents ? Partage de solutions

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!

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