Spring Cache+Redis cache data

Spring Cache+Redis cache data

Cache: In order to improve query speed , it is
suitable for cache scenarios: data that is not frequently modified, fixed data, and frequently queried data.

 Spring Cache
   是一个非常优秀的缓存组件,自Spring3.1起,提供了类似于@Transactional注解事务的注解Cache支持,且提供了Cache抽象,方便切换各种低层Cache(如:redis);

The benefits of using Spring Cache:
1. Provides a basic Cache abstraction to facilitate switching various low-level Caches.
2. Similar to transactions, the cache logic can be transparently applied to our business code by annotating Cache, and it can be completed with less code;
3. When providing transaction rollback, the cache is automatically rolled back;
4 .Support more complex caching logic;

Redis 

1. What is it: REmote DIctionary Server (remote dictionary server)
Redis installation under Windows
1.1 Unzip the redis package
1.2. Open the cmd command window
1.3. Enter the file path you just unzipped
1.4. Then enter the redis-server redis.windows.conf command

Next, deploy Redis as a service under windows. First close the previous window and open a new cmd command window,
then enter the command redis-server --service-install redis.windows.conf

Common redis instructions
Uninstall the service: redis-server --service-uninstall
Start the service: redis-server --service-start
Stop the service: redis-server --service-stop

Switch to the decompressed redis directory, open it with cmd,
enter redis-cli
2. Install redis
2.1 in the linux system and install docker

  #卸载旧版本
  sudo yum remove docker docker-common container-selinux docker-selinux docker-engine
  sudo yum remove -y docker-*
  #查询版本:无则说明卸载完毕
  docker version
  #安装最新docker
  sudo yum update
  sudo yum install -y yum-utils
  sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  sudo yum makecache fast
  sudo yum install docker-ce docker-ce-cli containerd.io
  #查询docker版本
  yum list docker-ce --showduplicates | sort -r
  #选择版本安装
  yum install -y docker-ce-[docker版本]
  #启动docker
  sudo systemctl start docker
  #搜索redis
  docker search redis
  #docker 拉redis镜像
  docker pull redis:latest
  #查询docker镜像是否有redis
  docker pull redis:latest
  #启动redis
  docker run -itd --name redis -p 6379:6379 redis
  #查看是否启动完成
  docker ps
  #客户端登录redis
  docker exec -it redis /bin/bash
  redis-cli
  #停止redis
  docker stop redis
  #删除redis
  docker rm redis
  #获取docker中所有容器id
  docker container ls -a
  #根据容器中id停止相应的镜像
  docker container stop container_ID
  #删除redis镜像前应先停止redis
  docker container rm  CONTAINER_ID //或CONTAINER_NAME
  #批量获取容器ID
  docker container ls -a -q
  #批量获取镜像ID
  docker image ls -a -q   
  #批量停止容器
  docker container   stop   $(docker  container  ls   -a  -q)
  #批量删除容器
  docker   container   rm  $(docker  container  ls   -a  -q)
  #通过image的id来指定删除镜像
  docker rmi <image id>
  #想要删除untagged images,也就是那些id为<None>的image的话可以用
  docker rmi $(docker images | grep "^<none>" | awk "{print $3}")
  #要删除全部images
  docker rmi $(docker images -q)
  #访问容器
  docker exec -it redis bash
  #使用redis-cli访问容器内redis
  docker exec -it redis redis-cli	
#开始测试redis,进入
redis-cli
#添加key value
set A 1
#通过key 查询value
get A
#查询所有key
keys *
#删除key
del A
NoSQL

MySQL master-slave separation: Buyer a library. Seller a library.

NoSQL means "more than sql"; it generally refers to non-relational databases: the classic formula: ACID (consistent principles, independent isolation); this type of database storage does not require a fixed schema. Scale horizontally without redundant operations.

Nosql databases have very high read and write characteristics.
NOSQL does not need to establish fields for the data to be stored in advance, and can store freely defined data formats at any time. in relational databases.
Adding or deleting fields is a very troublesome thing. If it is a table with a very large amount of data, adding fields is a nightmare.

RDBMS (Relational Database) VS NoSQL
RDBMS: 1. Structured Query Language (SQL)

NoSQL
Note: What can NoSQL do: easy expansion, high performance for large data volumes, diverse and flexible data models, traditional RDBMS VS NoSQL
1. Not just sql;

The 3v+3 height in Nosql:
1. 3V in the era of big data: massive Volume; diverse Variety; real-time Velocity
2. The 3 heights of Internet demand: high concurrency; high scalability (horizontal expansion: one machine cannot do it, one row dry); high performance (single point of failure);

Go IOE: Remove IBM minicomputers, Oracle databases and EMC storage devices

Load Balancing:
Introduction to Distributed and Clustering:
Distributed: Painless service modules (engineering) are deployed on multiple servers, and they communicate and call between them through Rpc/Rmi, providing external services and intra-group collaboration .
Cluster: The same service module is deployed on different multiple servers, and unified scheduling is performed through distributed invocation software to provide external services and access.

It is completely open source and free, written in C language, and complies with the BSD protocol. It is a high-performance (key/value) distributed memory database. It
is a NoSQL database that runs based on memory and supports persistence. It is one of the most popular NoSql databases. One,
also known as the data structure server

Three features of Redis

1.Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用
2.Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储
3.Redis支持数据的备份,即master-slave模式的数据备份

What can Redis do:

内存存储和持久化:redis支持异步将内存中的数据写到硬盘上,同时不影响继续服务
取最新N个数据的操作,如:可以将最新的10条评论的ID放在Redis的List集合里面
模拟类似于HttpSession这种需要设定过期时间的功能
发布、订阅消息系统
定时器、计数器

hashset hashmap
The bottom layer of hashset is hashmap

Explanation of miscellaneous basics after Redis is started

默认16个数据库,类似数组下表从零开始,初始默认使用零号库
> DBsize   查看当前数据库的key的数量
> SELECT   命令切换数据库 (eg:select 1 切换到第二个数据库)
> FLUSHDB  清空当前数据库
> FLUSHALL 清空所有的数据库 

Five data types of Redis:

1.String(字符串); 2.list(列表);3.Set (集合);4.Zset(sorted set:有序集合);5.hash 类似于Java中的map
redis的String可以包含任何数据,比如jpg图片或者序列化的对象。
redis列表是简单的字符串列表,按照插入顺序排序
redis的set是String类型的无序集合,它是通过hashtable实现的

1. The project integrates spring cache+redis
because the cache is also used for public use. All Service modules may use the cache. Feel free to add some configurations that depend on the service_util module, so that other service modules can be used.

1.1.service_util add dependencies

   <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <!--spring2.x集成redis所需要的common-pool2-->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
        <version>2.6.0</version>
    </dependency>
    <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>

1.2 Configuration class

package com.zhsh.cyz.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.lang.reflect.Method;
import java.time.Duration;

/**
 * @description:
 * @author:cyz
 * @time:2021/10/25 0025
 */
@Configuration
//开启缓存
@EnableCaching
public class RedisConfig {
    
    
    /**
      *@description 自定义key规则
      *@params 
      *@return 
      *@author cyz
      *@Date 2021/10/25 0025
      */
    @Bean
    public KeyGenerator keyGenerator() {
    
    
        return new KeyGenerator() {
    
    
            @Override
            public Object generate(Object target, Method method, Object... params){
    
    
                StringBuilder sb=new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj:params) {
    
    
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }
    /**
      *@description 设置redisTemplate规则
      *@params redisConnectionFactory
      *@return 
      *@author cyz
      *@Date 2021/10/25 0025
      */
    public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
    
    
        RedisTemplate<Object,Object> redisTemplate=new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer=new Jackson2JsonRedisSerializer(Object.class);
        //解决查询缓存转换异常的问题
        ObjectMapper om=new ObjectMapper();
        //指定要序列化的域,field,get和set以及修饰符范围,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);


        //序列号key value
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
    /**
      *@description 设置CacheManager缓存规则
      *@params factory
      *@return 
      *@author cyz
      *@Date 2021/10/25 0025
      */
    public CacheManager cacheManager(RedisConnectionFactory factory){
    
    
        RedisSerializer<String> redisSerializer=new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer=new Jackson2JsonRedisSerializer(Object.class);
        
        //解决查询缓存转换异常的问题
        ObjectMapper om=new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        //配置序列化(解决乱码问题),过期时间600秒
        RedisCacheConfiguration config=RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();
        RedisCacheManager cacheManager=RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
    }
    
}

Description:
@EnableCaching: mark the annotation @EnableCaching, enable caching, and configure the Redis cache manager. The @EnableCaching annotation triggers the post-processor to check whether there is a cache annotation in the public method of each Spring bean. If such an annotation is found, it will automatically Create a proxy to intercept method calls and handle corresponding caching behavior.

1.3 Add redis to service_cmn configuration file application.properties

spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.database=0
spring.redis.timeout=1800000

spring.redis.lettuce.pool.max-active=20
spring.redis.lettuce.pool.max-wait=-1
#最大阻塞等待时间(负数代表没有限制)
spring.redis.lettuce.pool.max-idle=5
spring.redis.lettuce.pool.min-idle=0

# 设置缓存默认超过期时间为30秒
spring.cache.redis.time-to-live.seconds=10
spring.cache.redis.use-key-prefix=true
spring.cache.redis.key-prefix=dev
spring.cache.redis.cache-null-values=false
spring.cache.redis.time-to-live=20s

2. Use spring Cahce
2.1 Common cache tags
2.1.1 The cache tag @Cacheable caches
the returned results according to the method. When the next request is made, if the cache exists, the cached data is directly read and returned. If the cache does not exist, the method is executed. , and store the returned results in the cache, which is generally used in query methods.
Looking at the source code, the property values ​​are as follows:

属性/方法名       解释
value           缓存名,必填,它指定了你的缓存存放在哪块命名空间
cacheNames 与value差不多,二选一即可
key             可选属性,可以使用SpEL标签自定义缓存的key

2.1.2 Cache @CachePut (after adding a data, the data will be synchronized to the cache)
The method using this annotation flag will be executed every time, and the result will be stored in the specified cache. Other methods can directly read the cached data from the response cache without querying the database, and are generally used in new methods.
Looking at the source code, the property values ​​are as follows:

属性/方法名      解释
value           缓存名,必填,它指定了你的缓存存放在哪块命名空间
cacheNames 与value差不多,二选一即可
key             可选属性,可以使用SpEL标签自定义缓存的key

2.1.3 Cache @CacheEvict
The method using this annotation flag will clear the specified cache. Generally used in update or delete methods to
view the source code, the attribute values ​​are as follows:

属性/方法名         解释
value             缓存名,必填,它指定了你的缓存存放在哪块命名空间
cacheNames 与value差不多,二选一即可
key               可选属性,可以使用SpEL标签自定义缓存的key
allEntries        是否清空所有缓存,默认为false。如果指定为true,则方法调用后将立即清空所有的缓存
beforeInvocation  是否在方法执行前就清空,默认为false,如果指定为true,则在方法执行前就会清空缓存。

The data cache can be completed by directly adding corresponding annotations to the implementation class of the service layer. The key value of the cache is the value value + the implemented method.

/**
 * @description: 数据字典控制类
 * @author:cyz
 * @time:2021/10/22 0022
 */
 @Cacheable(value = "dict",keyGenerator = "keyGenerator")
 @Override
  public List<AreaCode> FindDataById(Long id) {
    
    
      QueryWrapper<AreaCode> wrapper=new QueryWrapper<>();
      wrapper.eq("pid",id);
      List<AreaCode> list=baseMapper.selectList(wrapper);
      for (AreaCode ac:list) {
    
    
          Long acId = ac.getId();
          boolean isChild=this.isChildren(acId);
          ac.setHasChildren(isChild);
      }
      return list;
  }
//导入数据功能
@Override
@CachePut(value="dict")
public void importData(MultipartFile file) {
    
    
    try {
    
    
        //读取file流,同时需要进行监听配置,在监听配置中将数据写入数据库中
        EasyExcel.read(file.getInputStream(),DataVo.class,new DataListener(baseMapper)).sheet().doRead();
    }catch(Exception e){
    
    
        e.printStackTrace();
    }
}
//删除某一条数据
@Override
@CacheEvict(value="dict",allEntries=true)
public void delData(String id){
    
    
baseMapper.deldatabyId(id);
}

insert image description here

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324352522&siteId=291194637