Spring Cache+Redis 缓存数据

Spring Cache+Redis 缓存数据

缓存:为了提高查询速度
适合做缓存的场景:不经常修改数据,固定的数据,经常查询的数据。

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

使用Spring Cache的好处:
1.提供基本的Cache抽象,方便切换各种低层Cache。
2.通过注解Cache可以实现类似于事务一样,缓存逻辑透明的应用到我们的业务代码上,且只需要更少的代码就可以完成;
3.提供事务回滚的时也自动回滚缓存;
4.支持比较复杂的缓存逻辑;

Redis 

1.是什么:REmote DIctionary Server(远程字典服务器)
redis安装Windows下
1.1解压redis包
1.2.打开cmd指令窗口
1.3.输入你刚才解压的文件路径
1.4.然后输入redis-server redis.windows.conf 命令

接下来部署Redis为windows下的服务 首先关掉上一个窗口再打开一个新的cmd命令窗口
然后输入指令redis-server --service-install redis.windows.conf

redis常用指令
卸载服务:redis-server --service-uninstall
开启服务:redis-server --service-start
停止服务:redis-server --service-stop

切换到解压的redis目录,利用cmd打开
输入redis-cli
2.linux系统中安装redis
2.1 安装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主从分离:买家一个库。卖家一个库.

NoSQL 意为”不仅仅是sql“;泛指非关系型数据库:经典的公式:ACID(原则一致,独立隔离);这类型的数据库存储不需要固定的模式。无需多余操作就可以横向扩展。

Nosql数据库具有非常高的读写特性。
NOSQL无需事先为要存储的数据建立字段,随时可以存储自在定义的数据格式。而关系数据库里。
增删字段是一件非常麻烦的事情。如果是非常大数据量的表,增加字段简直就是一个噩梦。

RDBMS(关系型数据库)VS NoSQL
RDBMS:1.结构化查询语言(SQL)

NoSQL
注意:NoSQL能做什么:易扩展,大数据量高性能,多样灵活的数据模型,传统RDBMS VS NoSQL
1.不仅仅是sql;

Nosql 中的3v+3高 :
1.大数据时代的3V:海量Volume;多样Variety;实时Velocity
2.互联网需求的3高:高并发;高可扩(横向扩展:一台机器干不了,一排干);高性能(单点故障);

去IOE:去除IBM小型机、Oracle数据库及EMC存储设备

负载均衡:
分布式和集群的简介:
分布式:不痛的多台服务器上面部署不痛的服务模块(工程),他们之间通过Rpc/Rmi之间通信和调用,对外提供服务和组内协作。
集群:不同的多台服务器上面部署相同的服务模块,通过分布式调用软件进行统一的调度,对外提供服务和访问。

是完全开源免费的,用C语言编写的,遵守BSD协议,是一个高性能的(key/value)分布式内存数据库,基于内存运行
并支持持久化的NoSQL数据库,是当前最热门的NoSql数据库之一,
也被人们称为数据结构服务器

Redis三种特性

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

Redis能干嘛:

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

hashset hashmap
hashset的底层就是hashmap

Redis启动后杂项基础知识讲解

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

Redis五大数据类型:

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

1.项目集成spring cache+redis
因为缓存也是公共使用,所有的Service模块都有可能使用缓存,随意把依赖于部分配置加在service_util模块,这样其他service模块都可以使用了

1.1.service_util添加依赖

   <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 配置类

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;
    }
    
}

说明:
@EnableCaching:标记注解@EnableCaching,开启缓存,并配置Redis缓存管理器,@EnableCaching注解触发后置处理器,检查每一个Spring bean的public方法是否存在缓存注解,如果找到这样的一个注释,自动创建一个代理拦截方法调用和处理相应的缓存行为。

1.3 service_cmn配置文件application.properties添加redis

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.使用spring Cahce
2.1常用缓存标签
2.1.1缓存标签@Cacheable
根据方法对其返回结果进行缓存,下次请求时,如果缓存存在,则直接读取缓存数据返回,如果缓存不存在,则执行方法,并把返回的结果存入缓存中,一般用在查询方法上。
查看源码,属性值如下:

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

2.1.2缓存@CachePut(添加一个数据后,将会把数据同步到缓存中)
使用该注解标志的方法,每次都会执行,并将结果存入指定的缓存中。其他方法可以直接从响应的缓存中读取缓存数据,而不需要再去查询数据库,一般用在新增方法上。
查看源码,属性值如下:

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

2.1.3缓存@CacheEvict
使用该注解标志的方法,会清空指定的缓存。一般用在更新或者删除方法上
查看源码,属性值如下:

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

直接在service层实现类中添加相应的注解即可完成对数据的缓存,缓存的key值为value值+实现的方法

/**
 * @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);
}

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七秒~车

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值