Utilisez la fonction d'abonnement aux messages de redis pour mettre à jour le cache local de la caféine dans l'application

1. Pourquoi mettre à jour le cache caféine ?

1.1, les avantages et les inconvénients du cache caféine

Dans l'environnement de production, le cache caféine est le cache local que nous utilisons dans l'application.
Son avantage est qu'il existe dans l'application et a la vitesse d'accès la plus rapide. Il répond généralement en moins de 1 ms.
L'inconvénient est qu'il n'est pas pratique de gérer, car il existe dans le Sur plusieurs serveurs Web à charge équilibrée,
il est difficile de le mettre à jour et de le supprimer comme la gestion du cache redis.

1.2, nous réglerons généralement le temps de cache de la caféine sur 5 minutes ou 10 minutes,

Mais lorsqu'une promotion à grande échelle démarre, si le cache n'a pas expiré,
les données affichées par le service Web ne seront pas mises à jour immédiatement.Comment
mettre à jour le cache in-app de plusieurs serveurs Web ?
L'utilisation de l'abonnement aux messages redis est l'une des solutions.Nous
envoyons un message à redis depuis l'arrière-plan, et
le service Web abonné à redis peut traiter le cache après avoir reçu le message,
afin de mettre à jour le cache sur plusieurs serveurs Web.

1.3, la mise en cache à plusieurs niveaux est généralement utilisée dans l'environnement de production,

Lorsque nous mettons à jour le cache de caféine,
nous ne devons pas accéder à la base de données pour éviter un accès simultané à la base de données.
Au lieu de cela, après la mise à jour de Redis,
le cache local obtient des données de Redis,
et un accès simultané de l'ordre de centaines ou de milliers est très stressant pour redis Petit

2. Informations sur le projet de démonstration

pom.xml ajouter pom au besoin

   <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
    </parent>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
   </dependency>
      
   <dependency>
         <groupId>com.github.ben-manes.caffeine</groupId>
         <artifactId>caffeine</artifactId>
   </dependency>

Initialiser redisTemple

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.omg.CORBA.portable.UnknownException;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {
    
    

    @Bean(name = "redisTemplate")
    @ConditionalOnClass(RedisOperations.class)
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
    
    
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>  
        (Object.class);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.activateDefaultTyping(mapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(mapper);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // 指定 key 的序列化格式
        template.setKeySerializer(stringRedisSerializer);
        // 指定 hash 的 key 的序列化格式
        template.setHashKeySerializer(stringRedisSerializer);
        // 指定 value 的序列化格式
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // 指定 hash 的 value 的序列化格式
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

ajouter un écouteur

import club.chuige.appmanagement.common.tool.cache.CacheManagerTool;
import club.chuige.appmanagement.common.consts.CacheConstants;
import club.chuige.appmanagement.common.consts.Constants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;

@Configuration
public class RedisListenerConfig {
    
    

    @Autowired
    CacheManagerTool cacheManagerTool;

    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory redisConnectionFactory,
                                            MessageListenerAdapter listenerAdapter) {
    
    
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory);
        container.addMessageListener(listenerAdapter, new PatternTopic(CacheConstants.USER_CACHE));
        return container;
    }

    @Bean
    MessageListenerAdapter listenerAdapter() {
    
    
        return new MessageListenerAdapter(this, "receiveMessage");
    }

     // 接受到通知,清除本地缓存
    public void receiveMessage(String message) {
    
    
        String[] messages = message.split(Constants.SPLIT_COLON);
        CaffeineCache cache = cacheManagerTool.getCacheByName(messages[0]);
        cache.evict(messages[1]);

    }
}

Aop entoure d'opérations de mise à jour et de suppression, envoie des diffusions et invalide les caches locaux d'autres serveurs

  @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private void sendRedisTopic(String topic, String message) {
    
    
        redisTemplate.convertAndSend(topic, message);
    }

Je suppose que tu aimes

Origine blog.csdn.net/chuige2013/article/details/131000101
conseillé
Classement