缓存技术
- 缓存
- 模拟缓存
- Spring缓存技术
- 第三方缓存技术
- Ehcache缓存供应
- Redis缓存
- memcached缓存(国内)
- jetcache缓存供应商
- jetcache的基本使用
- 设置外部服务
- 设置本地服务
- jetcache方法缓存
- j2cache
缓存
- 什么是缓存
缓存是一种介于数据永久存储介质与数据应用之间的数据临时存储介质
使用缓存可以有效的减少低速数据读取过程的次数(例如磁盘IO),提高系统性能
缓存不仅可以用于提高永久性存储介质的数据读取效率,还可以提供临时的数据存储空间
模拟缓存
手动写一个模拟缓存的demo,这里我们在server层中模拟一个缓存
@Server
public class Bookserverimpl implements Bookserver{
@Autowired
private BookDao bookdao;
private HashMap<Integer,Book> cache=new HashMap<Integer,Book>();
public Book getById(Integer id){
Book book=cache.get(id);
if(book=null){
Book qubook=BookDao.selectById(id);
cache.put(id,qubook);
return qubook;
}
}
return cache.get(id);
}
这里面的HashMap对象充当一个缓存器,对数据库中的数据进行查询,先对缓存中进行查询,当缓存中有这个数据的时候就查询缓存中的数据,当缓存中没有的时候再在数据库中进行查询并添加到缓存器中
Spring缓存技术
SpringBoot提供了缓存技术,方便缓存使用
首先导入缓存的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
在启动类中加入注解 @EnableCaching表示启动缓存
@SpringBootApplication
@EnableCaching
public class SpringbootApplication{
}
在服务层使用缓存技术:
@Cacheable(value="cacheSpace",key="#id")
public Book getByid(Integer id){
}
但是这里有一个问题,在这个注解中也有向外读取的操作,我们应该将注解换成 @CachePut
value属性指创建一个存储空间,其中放入key的值,#id表示可以读取名为id 的值
上述操作就是spring官方默认的缓存技术,除此之外,spring还可以整合第三方的缓存技术,统一接口,实现高效开发
第三方缓存技术
Ehcache缓存供应
导入ehcache的依赖:
<dependency>
<groupId>ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>1.2</version>
</dependency>
在配置文件中设置cache的类型启用ehcache
spring:
cache:
type: ehcache
ehcache:
config: ehcache.xml
使用ehcache需要有一个其独立的配置文件,用来配置其中的设置
在配置文件当中缓存还可以多次进行配置,我再写一个defaultCache用name区分
<defaultCache
name="cacac"
....
/>
- 注意
当我们改换第三方技术的时候,原有的默认注解并没有进行改变,依然可以正常使用
Redis缓存
首先先导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
在配置文件中选择cache的类型为redis
redis:
host: localhost
port: 6379
redis的相关配置也在配置文件中进行配置
spring:
cache:
type: redis
redis:
use-key-prefix: true #是否使用前缀
cache-null-values: false #是否缓存空值
key-prefix: aa #指定前缀
time-to-live: 10s #最大活动周期
注意属性的层次尤其是redis
memcached缓存(国内)
下载memcached
地址:https://www.runoob.com/memcached/window-install-memcached.html
下载之后解压目录:
在管理员权限下运行cmd,进入到当前目录中输入命令安装并启动服务
当需要服务停止的时候输入memcached.exe -d stop
- memcached客户端选择
- Memcached Client for java:最早期客户端,稳定可靠,用户群广
- SpyMemcached: 效率更高
- Xmemcached: 并发处理好
我们这里采用技术更加先进的Xmemcached技术,但是SpringBoot未提供对xmemcached的整合,需要使用硬编码方式实现客户端初始化管理
首先导入依赖:
<dependency>
<groupId>com.googlecode.xmemcached</groupId>
<artifactId>xmemcached</artifactId>
<version>2.4.7</version>
</dependency>
写一个控制类
@Configuration
public class XmemcachedConfig {
@Bean
public MemcachedClient getmemcacheclient() throws IOException {
MemcachedClientBuilder memcachedClientBuilder=new XMemcachedClientBuilder("localhost:11211");
MemcachedClient memcachedClient=memcachedClientBuilder.build();
return memcachedClient;
}
}
像控制类中的配置信息还可以通过配置文件进行自定义配置:
memcached:
servers: localhost:11211
poolSize: 10 #连接池的最大连接数
opTimeout: 3000
自定义文件之后配置一个对应的属性类进行配置
@Component
@ConfigurationProperties(prefix="memcached")
@Data
public class Xmemcachedproperties{
private String servers;
private int poolSize;
private long opTimeout;
}
这个时候在配置类中就可以进行使用
@Configuration
public class XmemcachedConfig {
@Bean
public MemcachedClient getmemcacheclient() throws IOException {
MemcachedClientBuilder memcachedClientBuilder=new XMemcachedClientBuilder(memcachedproperties.getServers());
memcachedClientBuilder.setconnectionPoolSize(memcachedProperties.getPoolSzie()); //设置最大连接数
memcachedClientBuilder.setOptimeout(memcachedProperties.getOpTimeout());
MemcachedClient memcachedClient=memcachedClientBuilder.build();
return memcachedClient;
}
}
在服务类中注入使用
@Autowired
private MemcachedClient memcachedClient;
public String sendCodeTosms(String tele){
memcachedclient.set(tele,0,code); //第一个参数是key,第二个参数是过期时间,第三个参数是值,这句话需要try-catch抛出
}
jetcache缓存供应商
jetCache对SpringCache进行了封装,在原有功能基础上实现了多级缓存,缓存统计,自动刷新,异步调用,数据报表等功能
jetCache设定了本地缓存与远程缓存的多级缓存解决方案
本地缓存:(local)
- LinkedHashMap
- Caffeine
远程缓存:(remote) - Redis
- Tair
jetcache的基本使用
设置外部服务
首先先导入依赖:
<dependency>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-starter-redis</artifactId>
<version>2.6.2</version>
</dependency>
在配置文件中配置jetcache:
jetcache与spring是同一级别的配置
jetcache:
remote: #配置远程管理
default: #管理模式,相当于之前配置文件中的ehcache配置文件中的name可以有多个
type: redis
host: localhost
port: 6379
poolConfig: #对应的配置
maxTotal: 50 #设置最大连接数,必须写poolConfiig,其中最少也要写maxTotal的配置否则会报错
keyConvertor: fastjson #默认在缓存中将java对象数据转换为json字符串,也可以将json字符串转换为java
calueEncoder: java
calueEncoder: java #规定缓存中值进行转换时,转换成什么类型的数据
sms: #第二个管理模式
在开启类中jetcache启用缓存开关
@springbootApplication
@EnableCreateCacheAnnotation
public class SpringbootApplication{
}
自定义缓存空间
//注解第一个属性相当于值前的前缀,expire设置过期时间,3600默认单位秒,可以通过第三个参数设置单位
@CreateCache(name="jetcache",expire=3600,timeUnit=TimeUnit.SECONDS)
//自定义缓存空间,泛型中对应的是key和value的值
private Cache<String,String> jetcache;
存入缓存:
jetcache.put("tele",code);
读取缓存:
jetcache.get();
- 切换管理模式
在配置中配置第二个管理模式sms如上所讲,那要如何进行切换
@CreateCache(area="sms",name="",expire=)
通过注解进行管理模式的切换,这样命名空间就会用对应的管理模式进行创建空间
设置本地服务
同样在配置文件中进行配置:
jetcache:
local:
default:
type: linkedhashmap
keyConvertor: fastjson
limit: #缓存的数据量
通过注解实现本地远程进行切换:
@CreateCache(name="",expire=,cacheType=Cache.LOCAL)//有三个值可以进行切换
- jetcache配置属性信息
jetcache方法缓存
如果需要启动方法缓存需要在启动类上面加入方法缓存的注解
@springbootApplication
@EnableCreateCacheAnnotation
@EnableMethodCache(basepackages="包名") //注解中的属性需要添加一个包名,所要添加注解的方法就在这个包下
public class SpringBootCacheApplicaton{
}
在方法上使用注解 @Cached进行缓存处理:
@Cached(name="jetcache_",key="#id",expire=3600)
public Book getbyId(Integer id){
return bookDao.getByid(id);
}
@Cached
与@CreateCache
的区别:
- 用途: @CreateCache 用于创建和直接操作缓存实例;@Cached 用于自动处理方法返回值的缓存。
- 操作: 使用 @CreateCache 时,开发者需要手动从缓存中获取和存储数据;而 @Cached 则自动化这个过程,使得方法执行与缓存透明化。
- 灵活性: @CreateCache 提供更多的控制权和灵活性,因为您可以直接操作缓存;@Cached 更简单易用,适合那些希望自动缓存方法返回结果的场景。
注意前面提到的jecache配置文件中的配置:keyConvertor:fastjson
我们提到它可以将java对象数据转换为json格式的字符串存储在缓存当中,而jetcache缓存底层通过序列化与反序列化的机制进行转换,这时我们首先应该将实体类对象序列化,这样才能够将序列化后的java对象数据进行转换:
@Data
public class Book implements Serializable{
private Integer id;
private String name;
}
接着进行操作:如果此时我们进行更新操作,此时缓存中的对应数据需要同步进行更新,那么此时,我们在进行更新操作的时候可以通过注解 @Cacheupdate同步进行更新操作:
@Cacheupdate(name="book_",key="#book.id",value="#book")
public boolean update(Book book){
return bookDao.updayeById(book)>0;
}
同时在进行删除操作的时候也应该通过注解 @CacheInvalidate在缓存中进行同步操作:
@CacheInvalidate(name="book_",key="#id")
public boolean delete(Integer id){
return bookDao.delete(id)>0;
}
通过以上三个操作就会显示出来一个问题,当多个用户同时操作一个数据的时候,可能会出现B用户操作后缓存同步完毕,A用户操作之后缓存没有进行同步看到的还是之前存在的数据这时就会出错:
我们可以通过注解 @CacheRefresh进行定时刷新,刷新缓存数据
@Cached(...)
@CacheRefresh(refresh=10)
jetcache对应的操作信息可以通过配置进行查看:
jetcache:
statIntervalMinutes: 1 #等待一分钟将一分钟内对缓存的操作进行分析统计并输出在控制台上
j2cache
j2cache 是一个缓存整合框架,可以提供缓存的整合方案,使各种缓存搭配使用,自身不提供缓存功能
这里我们基于 encache + redis 进行整合讲解j2cache
第一步导入依赖:
<!--在j2cache-spring-boot2-starter中就包含了redis的依赖文件-->
<dependency>
<groupId>net.oschina.j2cache</groupId>
<artifactId>j2cache-spring-boot2-starter</artifactId>
<version>2.8.0-release</version>
</dependency>
<dependency>
<groupId>net.oschina.j2cache</groupId>
<artifactId>j2cache-core</artifactId>
<version>2.8.4-release</version>
</dependency>
<dependency>
<groupId>ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>1.2</version>
</dependency>
然后在配置文件中进行配置:
server:
port: 80
j2cache:
config-location: j2cache.properties
j2cache的配置文件是properties类型,在配置文件当中配置多级缓存
# 一级缓存
j2cache.L1.provider_class =ehcache
ehcache.configXml =ehcache.xml
#设置是否启用二级缓存
j2cache.l2-cache-open=false
# 二级缓存
j2cache.L2.provider_class=net.oschina.j2cache.cache.support.redis.SpringRedisProvider
j2cache.L2.config_section=redis
redis.hosts=localhost:6379
#一级缓存中的数据如何到达二级缓存
j2cache.broadcast=net.oschina.j2cache.cache.support.redis.SpringRedisPubSubPolicy
二级缓存的供应商应该配置j2cache中redis的SpringRedisProvider类
如何使用j2cache:
//定义一个缓存对象
@Autowired
private CacheChannel cacheChannel;
//在方法中使用该对象进行缓存的处理
cacheChannel.set("sms",tele,code);
String code=cacheChannel.get("sms",smsCode.getTele()).asString();//将我们的值变化为String类型的值