REDIS12_ Overview of spring cache, @ Cacheable, @ CacheEvict, @ Caching, @ CachePut

① . Spring Cache overview

  • ① . how to find the official documentation of Spring Cache
    (https://docs.spring.io/spring-framework/docs/5.2.17.BUILD-SNAPSHOT/spring-framework-reference/integration.html#cache)

  • ② . Spring has defined org.springframework.cache.Cache and org.springframework.cache.Cache Manager interfaces since 3.1 to unify different caching technologies, and supports the use of JCache(JSR-107) annotations to simplify our development

  • ③ JSR-107 defines five core interfaces to implement cache operations, namely cachengprovider, CacheManager, cache, entry and Expiry

  • ④ . each time a method requiring caching function is called, Spring will check whether the specified target method of the specified parameter has been called; If yes, get the result of the method call directly from the cache. If not, call the method and cache the result and return it to the user. Get directly from cache for next call

  • ⑤ . detailed explanation of common annotations of SpringCache

annotationexplain
@CacheableTriggers the operation of saving data to the cache
@CacheEvictTriggers the deletion of data from the cache
@CachePutUpdate cache double write mode does not affect method execution
@CachingCombine the above operations
@CacheConfigShare the same configuration of the cache at the class level

② @ Cacheable. Spring cache entry list

  • ① . import the pom file and add @ EnableCaching on the main startup class
<!--introduce redis-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
        <exclusion>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!--cache-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>   
@EnableCaching
@SpringBootApplication
public class testSpringCache{
    public static void main(String[] args) {
        SpringApplication.run(testSpringCache.class, args);
    }

}
//application.properties
spring.cache.type=redis
#spring.cache.cache-names=
  • ② 2. Business
 /**
  * @Cacheable
  *(The results representing the current method need to be cached. If there are in the cache, the method does not need to be called
  *If there is no in the cache, the method will be called, and finally the result of the method will be put into the cache)
  *1,For each data to be cached, we specify the cache to be put into that name (cache partition, divided by business type)
  *2,Default behavior
  *   (1). If there is in the cache, the method is no longer called
  *   (2). key It is automatically generated by default, including the cache name:: simplekey (automatically generated key value)
  *   (3). The value of the cached value. By default, jdk serialization mechanism is used to save the serialized data to redis
  *   (4). The default expiration time is - 1
  */
@Cacheable(value={"category"})
@Override
public List<CategoryEntity> getLevel1Category() {
    long l= System.currentTimeMillis();
    QueryWrapper<CategoryEntity> wrapper = new QueryWrapper<>();
    wrapper.eq("parent_cid",0);
    List<CategoryEntity> entities = baseMapper.selectList(wrapper);
    log.info("Time consuming:"+(System.currentTimeMillis()-l));
    return entities;
}
  • ③ . test results:
  1. If there is in the cache, the method is no longer called
  2. The key is automatically generated by default, including the cache name:: simplekey (automatically generated key value)
  3. The value of the cached value. By default, jdk serialization mechanism is used to save the serialized data to redis
  4. The default expiration time is - 1
  • ④ . specify your own key and set the expiration time
//application.properties
spring.cache.type=redis
#spring.cache.cache-names=
#Set the survival time in ms
spring.cache.redis.time-to-live=3600000
/**
custom
(1). Specify the key attribute of the generated cache and receive an spl expression
 Detailed documentation: https://docs.spring.io/spring-framework/docs/5.2.16.RELEASE/spring-framework-reference/integration.html#cache-spel-context
(2). Specifies the lifetime of cached data (TTL is modified in the configuration file)
*/

@Cacheable(value={"category"},key = "'Level1Categorys'")
@Override
public List<CategoryEntity> getLevel1Category() {
    long l= System.currentTimeMillis();
    QueryWrapper<CategoryEntity> wrapper = new QueryWrapper<>();
    wrapper.eq("parent_cid",0);
    List<CategoryEntity> entities = baseMapper.selectList(wrapper);
    log.info("Time consuming:"+(System.currentTimeMillis()-l));
    return entities;
}

  • ⑤ . if you use #root.method.name
  @Cacheable(value={"category"},key = "#root.method.name")

③ . JSON format conversion, null value cache

  • ① . in the above configuration, the name can be specified and the expiration time has been configured. The JSON format has not been solved

  • ② . configuration principle of SpringCache

*   CacheAutoConfiguration Imported RedisCacheConfiguration,RedisCacheConfiguration Cache manager is automatically configured RedisCacheManager
*   RedisCacheManager->Initialize all caches->Each cache determines what configuration to use->Initialize according to the name configured in the configuration file,Decide which configuration to use(redisCacheConfiguration)
*   ->If redisCacheConfiguration Use what you have,If not, use the default configuration
*   ->Want to change the configuration,Just put one in the container RedisCacheConfiguration
*   ->Will be applied to the current RedisCacheManager In all caches managed(Cache partition)
  • ③ . create a new configuration class for JSON format conversion
//application.properties
spring.cache.type=redis
#spring.cache.cache-names=
#Set the survival time in ms
spring.cache.redis.time-to-live=3600000
#If a prefix is specified, the prefix we specified will be used. If not, the name of the cache will be used as the prefix by default
#CACHE_getLevel1Category
spring.cache.redis.key-prefix=CACHE_
#Prefix is used by default
#If this is started, the cached key=getLevel1Category, and there is no CACHE
spring.cache.redis.use-key-prefix=false
#Whether to cache null values to prevent cache penetration
spring.cache.redis.cache-null-values=true
@EnableConfigurationProperties(CacheProperties.class)
@EnableCaching
@Configuration
public class MyCacheConfig {
    /**
     * For the configuration in the configuration file to take effect, you need to add @ EnableConfigurationProperties(CacheProperties.class)
     * @param cacheProperties
     * @return
     */
    @Bean
    RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties){
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
        //The value becomes JSON format
        config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
        CacheProperties.Redis redisProperties = cacheProperties.getRedis();
        //Take all configurations in the configuration file into effect
        if (redisProperties.getTimeToLive() != null) {
            config = config.entryTtl(redisProperties.getTimeToLive());
        }
        if (redisProperties.getKeyPrefix() != null) {
            config = config.prefixKeysWith(redisProperties.getKeyPrefix());
        }
        if (!redisProperties.isCacheNullValues()) {
            config = config.disableCachingNullValues();
        }
        if (!redisProperties.isUseKeyPrefix()) {
            config = config.disableKeyPrefix();
        }
        return config;
    }
}

④ Use of @ CacheEvict, @ Caching, @ CachePut

  • ① . @ CacheEvict: triggers the deletion of data from the cache (equivalent to failure mode)

  • ② . @ Caching: combine the above operations

  • ③ . @ CachePut: method execution is not affected. Update cache (double write mode) needs a return value

    /**
     * Storing the same type of data can be specified as the same partition. By default, the partition name is the prefix of the cache
     * (We need to turn off the use of prefixes in the configuration file)
     * @param category
     */
    //@CacheEvict(value = "category",key = "'getLevel1Category'")
//    @Caching(evict = {
//            @CacheEvict(value = "category",key = "'getLevel1Category'"),
//            @CacheEvict(value = "category",key = "'getCatalogJson'")
//    })
    //Delete all data in the category partition
    //@CacheEvict(value = "category",allEntries = true) / / failure mode
    @Transactional
    @Override
    public void updateCasCade(CategoryEntity category) {
        this.updateById(category);
        categoryBrandRelationService.updateCategory(category.getCatId(),category.getName());
    }
//application.properties
spring.cache.type=redis
#spring.cache.cache-names=
#Set the survival time in ms
spring.cache.redis.time-to-live=3600000
#If a prefix is specified, the prefix we specified will be used. If not, the name of the cache will be used as the prefix by default
#CACHE_getLevel1Category
#spring.cache.redis.key-prefix=CACHE_
#Prefix is used by default
#If this is started, the cached key=getLevel1Category, and there is no CACHE
#spring.cache.redis.use-key-prefix=false
#Whether to cache null values to prevent cache penetration
spring.cache.redis.cache-null-values=true

⑤ . principles and shortcomings of SpringCache

  • ① . read mode
  1. Cache penetration: query a null data. Solution: cache empty data through spring. Cache. Redis. Cache null values = true
  2. Cache breakdown: a large number of concurrent queries come in and query an expired data at the same time. Solution: lock? It is unlocked by default;
  3. Use sync = true to solve the breakdown problem
  4. Cache avalanche: a large number of Keys expire at the same time. Solution: add random time.
// Solve cache breakdown locking 
@Cacheable(value={"category"},key = "#root.method.name",sync = true)
  • ② . write mode (CACHE consistent with database)
  1. Read write lock.
  2. Introduce Canal to sense the update of MySQL and update Redis
  3. Read more and write more. Just go to the database to query
  • ③ . summary
  1. General data (for data with more reads and less writes, timeliness and low consistency requirements, spring cache can be used):
  2. Write mode (as long as the cached data has an expiration time)

Keywords: Java Spring mvc

Added by dfr574 on Thu, 02 Sep 2021 07:18:55 +0300