积少成多 ----  仅以此致敬和我一样在慢慢前进的人儿

相关内容:

    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 缓存的更多相关文章

  1. SpringBoot学习笔记(10)-----SpringBoot中使用Redis/Mongodb和缓存Ehcache缓存和redis缓存

    1. 使用Redis 在使用redis之前,首先要保证安装或有redis的服务器,接下就是引入redis依赖. pom.xml文件如下 <dependency> <groupId&g ...

  2. spring boot 2.0.4 Redis缓存配置

    spring boot 2 使用RedisTemplate操作redis存取对象时,需要先进行序列化操作 import org.springframework.cache.CacheManager; ...

  3. springboot(九) Cache缓存和Redis缓存

    1. Cache缓存 1.1 缓存的概念&缓存注解 Cache 缓存接口,定义缓存操作.实现有:RedisCache.EhCacheCache.ConcurrentMapCache等 Cach ...

  4. spring boot:使用spring cache+caffeine做进程内缓存(本地缓存)(spring boot 2.3.1)

    一,为什么要使用caffeine做本地缓存? 1,spring boot默认集成的进程内缓存在1.x时代是guava cache 在2.x时代更新成了caffeine, 功能上差别不大,但后者在性能上 ...

  5. 本地缓存,Redis缓存,数据库DB查询(结合代码分析)

    问题背景 为什么要使用缓存?本地缓存/Redis缓存/数据库查询优先级? 一.为什么要使用缓存 原因:CPU的速度远远高于磁盘IO的速度问题:很多信息存在数据库当中的,每次查询数据库就是一次IO操作所 ...

  6. spring cache会默认使用redis作为缓存吗?

    web项目中,只需要配置 redis 的IP,端口,用户名和密码就可以使用redis作为缓存了,不需要在在java 代码中配置redisConfig,redisConfig只是作为缓存配置的辅助,比如 ...

  7. 搞懂分布式技术14:Spring Boot使用注解集成Redis缓存

    本文内容参考网络,侵删 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutor ...

  8. 【开源项目系列】如何基于 Spring Cache 实现多级缓存(同时整合本地缓存 Ehcache 和分布式缓存 Redis)

    一.缓存 当系统的并发量上来了,如果我们频繁地去访问数据库,那么会使数据库的压力不断增大,在高峰时甚至可以出现数据库崩溃的现象.所以一般我们会使用缓存来解决这个数据库并发访问问题,用户访问进来,会先从 ...

  9. 使用 Spring data redis 结合 Spring cache 缓存数据配置

    使用 JavaConfig 方式配置 依赖 jar 包: jedis.spring-data-redis 首先需要进行 Redis 相关配置 @Configuration public class R ...

  10. Spring Cache缓存技术的介绍

    缓存用于提升系统的性能,特别适用于一些对资源需求比较高的操作.本文介绍如何基于spring boot cache技术,使用caffeine作为具体的缓存实现,对操作的结果进行缓存. demo场景 本d ...

随机推荐

  1. 2020年. NET Core面试题

    第1题,什么是ASP net core? 首先ASP net core不是 asp net的升级版本.它遵循了dot net的标准架构, 可以运行于多个操作系统上.它更快,更容易配置,更加模块化,可扩 ...

  2. 使用spring boot中的JPA操作数据库

    前言 Spring boot中的JPA 使用的同学都会感觉到他的强大,简直就是神器一般,通俗的说,根本不需要你写sql,这就帮你节省了很多时间,那么下面我们来一起来体验下这款神器吧. 一.在pom中添 ...

  3. Mysql基本配置以及常见问题

    以下是MYSQL的基本配置以及常见问题的解决方式 1.获取客户端 https://dev.mysql.com/downloads/ 有两种方式获取到MYSQL,一种是通过MySQL Community ...

  4. SpringBoot入门简易教程

    使用SpringBoot来开发一个简单的restful api网关功能,目标:实现对SpringBoot的简单入门. 1. 创建SpringBoot项目 可以通过spring官网(https://st ...

  5. appium启动app(ios)

    Appium启动APP至少需要7个参数 ​ 'platformVersion','deviceName'.'udid'.'bundleId'.'platformName'.'automationNam ...

  6. .Net快速上手Nlog日志组件

    目录 一.NLog 简介 二.NLog 安装 三. NLog 配置 四.程序代码中写日志 五.参考 一.NLog 简介 NLog是适用于各种.NET平台的灵活,免费的日志记录平台.NLog使写入多个目 ...

  7. yum回滚至Kubernetes1.15.7版本

    背景:升级Kubernetes版本从1.14.1-->1.17.0,官方说明不能跨版本升级,所以只好一个版本一个版本升级.最终升到1.17.0后发现API的格式有改动,之前的中间件版本很多不支持 ...

  8. 接口自动化测试框架 -- reudom

    reudom Automated testing framework based on requests and unittest interface. 基于 Unittest 和 Requests ...

  9. 微信小程序吸顶功能

    ---------------------------HTML------------------------ <view class="navbar-wrap">  ...

  10. 动态代理之 JDK 动态代理

    动态代理 动态代理源于设计模式中的代理模式,代理模式的主要作用就是使代理对象完成用户的请求,屏蔽用户对真实对象的访问.通过代理对象去访问目标对象来控制原对象的访问. 代理模式的最典型的应用就是 Spr ...