Redis combat - mettre en cache les données et résoudre la cohérence des données du cache et de la base de données

Définition du cache

Le cache ( Cache) est le tampon pour l'échange de données . Le cache communément connu est les données contenues dans le tampon , qui sont généralement obtenues à partir de la base de données et stockées dans le code local. Empêcher un accès excessif aux données de se précipiter vers le système, ce qui rendrait son thread opérationnel incapable de traiter les informations à temps et paralysé. Ceci est fatal pour les entreprises, la réputation des produits et l'évaluation des utilisateurs dans le développement réel ; les entreprises attachent donc une grande importance à la technologie de mise en cache, redis as Le middleware de mise en cache le plus couramment utilisé est également un site de test à haute fréquence pour les entretiens.

Objectif de l'utilisation du cache

Les données du cache sont stockées dans le code et le code s'exécute dans la mémoire. Les performances de lecture et d'écriture de la mémoire sont bien supérieures à celles du disque. Le cache peut réduire considérablement la pression de lecture et d'écriture sur le serveur causée par le accès utilisateur simultané . Dans le processus de développement réel, la quantité de données dans une entreprise varie de centaines de milliers à des dizaines de millions. S'il n'y a pas de cache pour une telle quantité de données, le système peut difficilement les prendre en charge. Par conséquent, les entreprises utiliseront une grande quantité de données. nombre de technologies de cache.

Comment utiliser le cache

Dans le développement actuel, un cache multi-niveaux sera construit pour augmenter encore la vitesse du système, par exemple : le cache local et le cache dans redis sont utilisés simultanément

Cache du navigateur : principalement le cache qui existe côté navigateur

Cache de couche d'application : peut être divisé en cache local Tomcat, comme la carte mentionnée précédemment, ou utiliser Redis comme cache

Cache de base de données : il y a un espace dans la base de données comme pool de mémoire tampon, et les données ajoutées, modifiées et vérifiées seront d'abord chargées dans le cache MySQL.

Cache CPU : Le plus gros problème des ordinateurs contemporains est que les performances du CPU se sont améliorées, mais la vitesse de lecture et d'écriture de la mémoire n'a pas suivi. Par conséquent, afin de s'adapter à la situation actuelle, les caches L1, L2 et L3 du CPU ont été ajouté.

Informations sur le magasin de cache

 L'interface d'informations du magasin a une grande concurrence et les données de requête ne peuvent pas être interrogées à partir de la base de données à chaque fois. Les données du magasin doivent être mises en cache dans Redis pour faire face à une concurrence élevée.

@GetMapping("/{id}")
public Result queryShopById(@PathVariable("id") Long id) {
    //这里是直接查询数据库
    return shopService.queryById(id);
}

Modèle de mise en cache et idées

La méthode de fonctionnement standard consiste à interroger le cache avant d'interroger la base de données. Si les données mises en cache existent, elles seront renvoyées directement à partir du cache. Si les données mises en cache n'existent pas, interrogez à nouveau la base de données, puis stockez les données dans Redis.

 Code

Notez que les données du cache ne définissent pas de délai d'expiration pour le moment. Afin de réduire la pression sur la base de données, le cache doit résider dans la mémoire, mais cela entraînera également un problème d'incohérence des données du cache avec le données de la base de données, ce qui conduit au problème de la stratégie de mise à jour du tampon .

@Override
    public Result queryById(Long id) {
        //根据业务代码组装key
        String key = CACHE_SHOP_KEY + id;
        //从redis中获取商铺信息
        String shopJson = stringRedisTemplate.opsForValue().get(key);
        if (StrUtil.isNotBlank(shopJson)) {
            //将json转化为shop对象直接返回
            Shop shop = JSONUtil.toBean(shopJson, Shop.class);
            return Result.ok(shop);

        }
        Shop shop = getById(id);
        if (shop == null) {
            return Result.fail("店铺不存在");
        }
        //将数据库查询的数据写入缓存
        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop));
        //返回
        return Result.ok(shop);

Stratégie de mise à jour du cache

La stratégie de mise à jour est principalement sélectionnée en fonction de l'entreprise. Dans ce projet, la stratégie de mise à jour de mise à jour active + élimination du délai d'attente est adoptée. L'élimination du délai d'attente est principalement utilisée comme stratégie de mise à jour garantie pour garantir que le cache est mis à jour de temps en temps. sans déclencher la mise à jour active. effacera le cache

La mise à jour du cache est une chose conçue par Redis pour économiser de la mémoire, principalement parce que les données de la mémoire sont précieuses. Lorsque nous insérons trop de données dans Redis, cela peut entraîner trop de données dans le cache, donc Redis traitera certaines données. Mise à jour, ou c'est plus approprié de le qualifier d’éliminé.

Élimination de la mémoire : Redis est automatique . Lorsque la mémoire Redis atteint la mémoire maximale que nous avons définie, elle déclenchera automatiquement le mécanisme d'élimination pour éliminer certaines données sans importance (vous pouvez définir la stratégie par vous-même)

Suppression du délai d'expiration : lorsque nous définissons le délai d'expiration ttl pour Redis, Redis supprimera les données expirées afin que nous puissions continuer à utiliser le cache.

Mise à jour active : On peut appeler manuellement la méthode de suppression du cache, qui est généralement utilisée pour résoudre le problème d'incohérence entre le cache et la base de données

 Solution d'incohérence des données du cache de base de données

Puisque la source de données de notre cache provient de la base de données et que les données de la base de données changeront , si les données de la base de données changent mais que le cache n'est pas synchronisé , il y aura un problème de cohérence à ce moment-là , et la conséquence est :

Lorsque les utilisateurs utilisent des données obsolètes dans le cache, des problèmes similaires de sécurité des données multithread se poseront, ce qui affectera l'activité, la réputation du produit, etc. ; comment les résoudre ? Il existe plusieurs options

Méthode de codage manuel Cache Aside Pattern : l'appelant du cache met à jour le cache après la mise à jour de la base de données, également connu sous le nom de schéma de double écriture

Modèle de lecture/écriture : il est complété par le système lui-même et le problème de la base de données et du cache est géré par le système lui-même.

Modèle de mise en cache Write Behind : l'appelant exploite uniquement le cache et d'autres threads traitent la base de données de manière asynchrone pour obtenir la cohérence finale.

L'utilisation de l'option 2 augmente la complexité du système, ce qui ne permet pas à l'appelant de résoudre les problèmes associés. L'option 3 aura une série de threads de sécurité, ce qui entraînera des caches de base de données incohérents. Après un examen approfondi, il est plus sûr de choisir le manuel codage .

étapes de codage manuel

  1. Supprimer le cache : invalidez le cache lors de la mise à jour de la base de données, puis mettez à jour le cache lors de l'interrogation. (Si le cache est mis à jour en même temps que la base de données, il y aura trop d'actions de mise à jour et les performances ne peuvent pas être garanties)
  2. Dans le système monolithique, placez les opérations de cache et de base de données dans une seule transaction pour garantir que lorsque la base de données est mise à jour avec succès, le cache doit également être ajouté avec succès, c'est-à-dire pour garantir que les deux opérations réussissent ou échouent en même temps.
  3. Faites d'abord fonctionner la base de données, puis supprimez le cache. Dans le cas du multithreading, le temps d'exploitation de la base de données est beaucoup plus long que le temps d'exploitation du cache Redis. Lorsque la base de données est écrite, le risque de défaillance du cache est faible. .

Garantir une cohérence en double écriture entre les magasins, les caches et les bases de données

  • Lors de l'interrogation d'un magasin en fonction de l'identifiant, si le cache manque, interrogez la base de données, écrivez le résultat de la base de données dans le cache et définissez le délai d'attente.
  • Lors de la modification d'un magasin en fonction de l'identifiant, modifiez d'abord la base de données, puis supprimez le cache

Ajouter un délai d'expiration lors de la configuration du cache Redis lors de l'ajout du cache

@Override
    public Result queryById(Long id) {
        //根据业务代码组装key
        String key = CACHE_SHOP_KEY + id;
        //从redis中获取商铺信息
        String shopJson = stringRedisTemplate.opsForValue().get(key);
        if (StrUtil.isNotBlank(shopJson)) {
            //将json转化为shop对象直接返回
            Shop shop = JSONUtil.toBean(shopJson, Shop.class);
            return Result.ok(shop);

        }
        Shop shop = getById(id);
        if (shop == null) {
            return Result.fail("店铺不存在");
        }
        //将数据库查询的数据写入缓存,并设置过期时间
        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), 30L,TimeUnit.MINUTES);
        //返回
        return Result.ok(shop);
    }

Nous avons décidé d'utiliser la stratégie de suppression pour résoudre le problème de double écriture. Lorsque nous modifions les données, nous supprimons les données dans le cache. Lorsque nous constatons qu'il n'y a pas de données dans le cache lors de l'interrogation, les dernières données seront chargées. depuis mysql , évitant ainsi l'incohérence de la base de données avec le cache, cette méthode doit être annotée avec @Transactional pour déclarer la transaction

@Transactional
@Override
public Result update(Shop shop) {
    Long id = shop.getId();
    //判断id是否为空,因为可以绕过前端直接发送请求,此步必须判断
    if (id == null) {
        return Result.fail("店铺id不能为空");
    }
    //更新数据库
    updateById(shop);
    //删除缓存
    stringRedisTemplate.delete(CACHE_SHOP_KEY + id);
    return Result.ok();
}

Je suppose que tu aimes

Origine blog.csdn.net/weixin_64133130/article/details/132378548
conseillé
Classement