Spring Cache 抽象(缓存抽象) Redis 缓存
积少成多 ---- 仅以此致敬和我一样在慢慢前进的人儿
相关内容:
https://blog.51cto.com/14230003/2369413?source=dra
https://www.iteye.com/blog/jinnianshilongnian-2001040
https://www.jianshu.com/p/931484bb3fdc
https://www.jianshu.com/p/734d0e0419cb
https://www.imooc.com/article/30466
https://blog.csdn.net/LouisQMei/article/details/79941725 (spring cache 个人觉得讲的还不错)
https://www.cnblogs.com/wangxiayun/p/10221695.html(这个好像是和springBoot 视频中相互对应的)
https://www.jianshu.com/p/712368507d81(为什么要使用redis 作为缓存)
问题一: 什么是缓存,为什么要使用缓存
1. 缓存是用于拉近使用者和数据之间的距离(这个好像是buffer的作用),使得用户在访问相同的数据的时候,不需要每次都从数据库中取出来而是在缓存中取
出来(当然是因为存在缓存中的数据的读取速度很快相对于从数据库中读取出来)
2. 使用缓存主要目的在于高性能,高并发(见链接一)
问题二: spring 中自带缓存机制吗? 如何实现的?
spring 中使用的缓存使用concurrentMap实现的,
如果是第三方使用缓存的话,只要实现CacheMannerger 接口即可
spring 自己内部设置了 spring cache, spring cachemanager 这样的接口, spring 自身也提供了一种实现, 是通过对 cachemanager 的实现,用concurrentMap
实现的, 第三方cache 缓存进来之后, 只需要实现spring cachemanager 这个接口即可, 如 redis, ehcache
问题三:什么是序列化
众所周知,类的对象会随着程序的终止而被垃圾收集器销毁。如果要在不重新创建对象的情况下调用该类,该怎么做?这就可以通过序列化将数据转换为字节序列
所以序列化是方便对象的持久化,便于存储。 把一个对象序列化后生成字节序列, 然后想再次使用这个对象的时候,直接读取字节序列,然后反序列化,就可以得到这个对象了
上面序列化和反序列化都是由JVM 独立执行的, 所以字节序列可以在任何环境下面,通过JVM 反序列化为对象
所以有两个点:
什么是序列化: 序列化是通过*** 将对象转化为字节序列的过程, 这个字节序列里面包含了对象的一些信息***
什么是反序列化: 反序列化是通过**** 将字节序列转化为一个对象的过程
问题: 那么什么样的类(对象)可以进行序列化
常规的类,实现Serializable接口,就可以
(你上面说的,我好像见过,但是我在类的里面又看到serialVersionUID = ** 这个, 这个是干什么的)
serialVersionUID 这个是为了保证反序列化成功的, 保证反序列化后生成的对象跟原来的对象是唯一的,用于辅助序列化的
具体的执行过程是: 对象在序列化的时候,也会将serialVersionUID 的信息也添加到字节序列中去, 然后在反序列化的时候,JVM会将字节流里面的serialVersionUID
与你要生成的对象的serialVersionUID 进行比较,如果相同,则进行反序列化,反之则反序列化失败(这个可能说的不对)
问题四: spring 自带的缓存机制中是否存在的问题?
spring 中的自带的缓存中,将对象序列化的时候,是将对象序列化为字节序列,所以在查看缓存的时候就带来了问题, 不易于查看。
问题五:为什么不用spring自带的,而使用 Redis做 缓存?
大概是因为其支持的数据类型比较多吧,如list、set、sortedset、hashmap、string,而memecache只能支持简单的数据类型。
另外redis可以完成一部份数据的持久化,而memecache完全将数据保存在内存中,不进行持久化,如果服务器出问题,数据
将全部丢失,另外,可能是redis底层实现优化比memecache好吧
注1:有一些sql语句,比如sql语句中含有自定义函数、自定义变量、含有不确定数据[NOW()、CURRENT_DATE()等]、还有
其他一些sql语句的查询语句是不会被加入到查询缓存中的,查询时也不会经过查询缓存
问题六: 导入redis缓存依赖之后, springBoot如何进配置的?
在导入spring-redis-starter 依赖之后,这个依赖里面已经存在了很多的自动配置类 如 RedisAutoConfig,自动配置了redisCachemanager ,
以及注册了 Redistemplate, StringRedisTemplate 用于对redis 进行操作,取代了客户端的作用。
因为springBoot 加载缓存的配置类的时候,有一套顺序, 即优先级高的配置类,在ioc 容器中,则springBoot 加载优先级高的配置。
因为导入 spring-redis-starter 依赖 自动配置的redis 缓存的配置的顺序(优先级)高于springBoot 默认使用的缓存,所以现在springBoot 就切换到redis 进行缓存
问题六:什么是FastJson
fastjson是一个java语言编写的高性能且功能完善的JSON库,它采用一种“假定有序快速匹配”的算法,把JSON Parse
的性能提升到了极致。
它的接口简单易用,已经被广泛使用在缓存序列化,协议交互,Web输出等各种应用场景中。
fastJson:用于将对象序列化为json字符串,并且可以将json字符串转化对象
鉴于上述: 可以使用fastJson 序列化工具, 替换原来的springBoot 中 redis 自动配置中的序列化方法
问题七:配置 Redis CacheManger 的流程
package com.qf.springboot01.config; import com.alibaba.fastjson.parser.ParserConfig;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.qf.springboot01.util.FastJsonRedisSerializer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.*; import javax.crypto.KeyGenerator;
import java.lang.reflect.Method;
import java.time.Duration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set; @Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport { /**
* 重写Redis序列化方式,使用Json方式:
* 当我们的数据存储到Redis的时候,我们的键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用的是JdkSerializationRedisSerializer,StringRedisTemplate默认使用的是StringRedisSerializer。
* Spring Data JPA为我们提供了下面的Serializer:
* GenericToStringSerializer、Jackson2JsonRedisSerializer、JacksonJsonRedisSerializer、JdkSerializationRedisSerializer、OxmSerializer、StringRedisSerializer。
* 在此我们将自己配置RedisTemplate并定义Serializer。
*
*/ // 存入redis时,默认使用的是JdkSerializationRedisSerializer,使得存入的数据全部序列化了,所需自定义一个RedisTemplate,使用其他序列化方式 //当redis依赖包导入的时候,默认的cache即可自动变成redis模式;如果只是导入cache的依赖,则默认的是simpleCacheManager;
// 使用redis缓存时,RedisCacheManager生成RedisCache后生成缓存时默认使用JdkSerializationRedisSerializer序列化(cache存储的时候) //当ioc容器内没有自定义的缓存管理器的时候---默认使用自带的;
//当通过@Bean在ioc容器中注入了以下管理器,则会使用自定义的管理器; // @Bean
// public CacheManager cacheManager(RedisConnectionFactory factory) {
// RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig(); // 生成一个默认配置,通过config对象即可对缓存进行自定义配置
// config = config.entryTtl(Duration.ofMinutes(1)) // 设置缓存的默认过期时间,也是使用Duration设置
// .disableCachingNullValues(); // 不缓存空值
//
// // 设置一个初始化的缓存空间set集合
// Set<String> cacheNames = new HashSet<>();
// cacheNames.add("my-redis-cache1");
// cacheNames.add("my-redis-cache2");
//
// // 对每个缓存空间应用不同的配置
// Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
// configMap.put("my-redis-cache1", config);
// configMap.put("my-redis-cache2", config.entryTtl(Duration.ofSeconds(120)));
//
// RedisCacheManager cacheManager = RedisCacheManager.builder(factory) // 使用自定义的缓存配置初始化一个cacheManager
// .initialCacheNames(cacheNames) // 注意这两句的调用顺序,一定要先调用该方法设置初始化的缓存名,再初始化相关的配置
// .withInitialCacheConfigurations(configMap)
// .build();
// return cacheManager;
// } @Bean
@Primary//当有多个管理器的时候,必须使用该注解在一个管理器上注释:表示该管理器为默认的管理器
public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
//初始化一个RedisCacheWriter
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
//序列化方式1
//设置CacheManager的值序列化方式为JdkSerializationRedisSerializer,但其实RedisCacheConfiguration默认就是使用StringRedisSerializer序列化key,JdkSerializationRedisSerializer序列化value,所以以下(4行)注释代码为默认实现
// ClassLoader loader = this.getClass().getClassLoader();
// JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer(loader);
// RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(jdkSerializer);
// RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
//序列化方式1---另一种实现方式
//RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig();//该语句相当于序列化方式1 //序列化方式2: 使用fastJson
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);//JSONObject
RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer);
RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair); //序列化方式3
//Jackson2JsonRedisSerializer serializer=new Jackson2JsonRedisSerializer(Object.class);
//RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(serializer);
//RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair); defaultCacheConfig = defaultCacheConfig.entryTtl(Duration.ofSeconds());//设置过期时间
// //设置默认超过期时间是30秒
// defaultCacheConfig.entryTtl(Duration.ofSeconds(30)); //初始化RedisCacheManager
RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig); //设置白名单---非常重要********
/*
使用fastjson的时候:序列化时将class信息写入,反解析的时候,
fastjson默认情况下会开启autoType的检查,相当于一个白名单检查,
如果序列化信息中的类路径不在autoType中,
反解析就会报com.alibaba.fastjson.JSONException: autoType is not support的异常
可参考 https://blog.csdn.net/u012240455/article/details/80538540
*/
ParserConfig.getGlobalInstance().addAccept("com.qf.springboot01.entities");
return cacheManager;
} /**
* 设置 redis 数据默认过期时间
* 设置@cacheable 序列化方式
* @return
*/
@Bean
public RedisCacheConfiguration redisCacheConfiguration(){
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofDays());
return configuration;
} @Bean(name = "redisTemplate")
@SuppressWarnings("unchecked")
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
//使用fastjson序列化
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
// value值的序列化采用fastJsonRedisSerializer
template.setValueSerializer(fastJsonRedisSerializer);
template.setHashValueSerializer(fastJsonRedisSerializer);
// key的序列化采用StringRedisSerializer
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setConnectionFactory(redisConnectionFactory);
return template;
} // @Bean
// public KeyGenerator KeyGenerator() {
// return new KeyGenerator(){
// 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();
// }
// };
// } }
Spring Cache 抽象(缓存抽象) Redis 缓存的更多相关文章
- SpringBoot学习笔记(10)-----SpringBoot中使用Redis/Mongodb和缓存Ehcache缓存和redis缓存
1. 使用Redis 在使用redis之前,首先要保证安装或有redis的服务器,接下就是引入redis依赖. pom.xml文件如下 <dependency> <groupId&g ...
- spring boot 2.0.4 Redis缓存配置
spring boot 2 使用RedisTemplate操作redis存取对象时,需要先进行序列化操作 import org.springframework.cache.CacheManager; ...
- springboot(九) Cache缓存和Redis缓存
1. Cache缓存 1.1 缓存的概念&缓存注解 Cache 缓存接口,定义缓存操作.实现有:RedisCache.EhCacheCache.ConcurrentMapCache等 Cach ...
- spring boot:使用spring cache+caffeine做进程内缓存(本地缓存)(spring boot 2.3.1)
一,为什么要使用caffeine做本地缓存? 1,spring boot默认集成的进程内缓存在1.x时代是guava cache 在2.x时代更新成了caffeine, 功能上差别不大,但后者在性能上 ...
- 本地缓存,Redis缓存,数据库DB查询(结合代码分析)
问题背景 为什么要使用缓存?本地缓存/Redis缓存/数据库查询优先级? 一.为什么要使用缓存 原因:CPU的速度远远高于磁盘IO的速度问题:很多信息存在数据库当中的,每次查询数据库就是一次IO操作所 ...
- spring cache会默认使用redis作为缓存吗?
web项目中,只需要配置 redis 的IP,端口,用户名和密码就可以使用redis作为缓存了,不需要在在java 代码中配置redisConfig,redisConfig只是作为缓存配置的辅助,比如 ...
- 搞懂分布式技术14:Spring Boot使用注解集成Redis缓存
本文内容参考网络,侵删 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutor ...
- 【开源项目系列】如何基于 Spring Cache 实现多级缓存(同时整合本地缓存 Ehcache 和分布式缓存 Redis)
一.缓存 当系统的并发量上来了,如果我们频繁地去访问数据库,那么会使数据库的压力不断增大,在高峰时甚至可以出现数据库崩溃的现象.所以一般我们会使用缓存来解决这个数据库并发访问问题,用户访问进来,会先从 ...
- 使用 Spring data redis 结合 Spring cache 缓存数据配置
使用 JavaConfig 方式配置 依赖 jar 包: jedis.spring-data-redis 首先需要进行 Redis 相关配置 @Configuration public class R ...
- Spring Cache缓存技术的介绍
缓存用于提升系统的性能,特别适用于一些对资源需求比较高的操作.本文介绍如何基于spring boot cache技术,使用caffeine作为具体的缓存实现,对操作的结果进行缓存. demo场景 本d ...
随机推荐
- 第二阶段:2.商业需求分析及BRD:1.产品需求管理
产品经理需要投入大量的时间在需求方面的工作. 一张图看出需求多么重要.各个方面的人物对需求的误解导致的后果. 首先收集需求 需求采集 可以用excel收集数据并整理 备注信息也很重要 有时候要跟提出人 ...
- 使用 AT 指令进行 Socket 通信
BC26 支持使用 Socket 进行 TCP 和 UDP 协议通信,这两个协议也是 BC26 支持的众多通信协议的基础.本文讲解如何使用这两个协议与服务器端进行通信.在学习这篇文章前,请首先使用AT ...
- Objection基本原理
1,Objection 的简介 就是一个依赖注入框架,github地址:https://github.com/atomicobject/objection 2,Objection 原理 3,Objec ...
- Django发送邮件方法
在Django中将渲染后的模板进行邮件发送,可以使用send_email方法 首先在settings.py中添加如下配置 # 邮件配置SSL加密方式 EMAIL_HOST = 'smtp.qq.com ...
- 【题解】CF894E Ralph and Mushrooms (缩点)
[题解]CF894E Ralph and Mushrooms (缩点) 这是紫?给个解方程算法 考虑一条边若可以重复遍历说明一定有环,有环的话一定会把环上的蘑菇榨干,考虑一条边从全部到榨干的贡献是多少 ...
- 敏捷开发:代码Review
热情高涨 代码走查作为一种流程形式,起初大家的参与热情非常高涨. 因为,自己可以学习到别人一些巧妙的思想,自己的代码和习惯都暴漏出来. 这个过程中不断地吸收和改正. 但是...... 我们一开始组织的 ...
- [Windows10]记一次修复注册表相关血案:该文件没有与之关联的应用来执行该操作。请安装应用,若已经安装应用,请在“默认应用设置”页面中创建关联。
今天闲得蛋疼清理了一下右键菜单,于是在之后某时刻使用Everything的“双击路径列打开目录”功能时发现异常: [Window Title] Everything.exe [Content] 该文件 ...
- Java集合概述(上)
Java集合概述(上) 前言 先说说,为什么要写这么一篇博客(我总是喜欢写原因).因为最近到年底了,正好又要准备面试,所以在做各方面的技术总结.而Java集合是Java非常重要的一部分,自己前前后后也 ...
- 欧拉-拉格朗日方程 The Euler-Lagrange Equation
在 paper: Bounded Biharmonic Weights for Real-Time Deformation 中第一次接触到 Euler-Lagrange 方程,简单记录一下. 泛函的定 ...
- netcore使用IOptions
{ "Logging": { "LogLevel": { "Default": "Information", " ...