快速掌握缓存技术:学习多个缓存供应商(ehcache,redis,memcached,jetcache,j2cache)

缓存技术

缓存

  • 什么是缓存

缓存是一种介于数据永久存储介质与数据应用之间的数据临时存储介质

使用缓存可以有效的减少低速数据读取过程的次数(例如磁盘IO),提高系统性能

缓存不仅可以用于提高永久性存储介质的数据读取效率,还可以提供临时的数据存储空间

模拟缓存

手动写一个模拟缓存的demo,这里我们在server层中模拟一个缓存

java 复制代码
@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提供了缓存技术,方便缓存使用

首先导入缓存的依赖:

java 复制代码
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>

在启动类中加入注解 @EnableCaching表示启动缓存

java 复制代码
@SpringBootApplication
@EnableCaching
public class SpringbootApplication{
}

在服务层使用缓存技术:

java 复制代码
@Cacheable(value="cacheSpace",key="#id")
public Book getByid(Integer id){
}

但是这里有一个问题,在这个注解中也有向外读取的操作,我们应该将注解换成 @CachePut

value属性指创建一个存储空间,其中放入key的值,#id表示可以读取名为id 的值

上述操作就是spring官方默认的缓存技术,除此之外,spring还可以整合第三方的缓存技术,统一接口,实现高效开发

第三方缓存技术

Ehcache缓存供应

导入ehcache的依赖:

java 复制代码
        <dependency>
            <groupId>ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>1.2</version>
        </dependency>

在配置文件中设置cache的类型启用ehcache

yml 复制代码
spring:
   cache:
      type: ehcache
      ehcache:
         config: ehcache.xml

使用ehcache需要有一个其独立的配置文件,用来配置其中的设置

在配置文件当中缓存还可以多次进行配置,我再写一个defaultCache用name区分

xml 复制代码
<defaultCache
    name="cacac"
    ....
    />
  • 注意

当我们改换第三方技术的时候,原有的默认注解并没有进行改变,依然可以正常使用

Redis缓存

首先先导入依赖

java 复制代码
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

在配置文件中选择cache的类型为redis

yml 复制代码
  redis:
    host: localhost
    port: 6379

redis的相关配置也在配置文件中进行配置

yml 复制代码
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客户端选择
  1. Memcached Client for java:最早期客户端,稳定可靠,用户群广
  2. SpyMemcached: 效率更高
  3. Xmemcached: 并发处理好

我们这里采用技术更加先进的Xmemcached技术,但是SpringBoot未提供对xmemcached的整合,需要使用硬编码方式实现客户端初始化管理

首先导入依赖:

java 复制代码
        <dependency>
           <groupId>com.googlecode.xmemcached</groupId>
            <artifactId>xmemcached</artifactId>
            <version>2.4.7</version>
        </dependency>

写一个控制类

java 复制代码
@Configuration
public class XmemcachedConfig {
    @Bean
    public MemcachedClient getmemcacheclient() throws IOException {
        MemcachedClientBuilder memcachedClientBuilder=new XMemcachedClientBuilder("localhost:11211");
        MemcachedClient memcachedClient=memcachedClientBuilder.build();
        return memcachedClient;
    }
}

像控制类中的配置信息还可以通过配置文件进行自定义配置:

yml 复制代码
memcached:
   servers: localhost:11211
   poolSize: 10               #连接池的最大连接数
   opTimeout: 3000

自定义文件之后配置一个对应的属性类进行配置

java 复制代码
@Component
@ConfigurationProperties(prefix="memcached")
@Data
public class Xmemcachedproperties{
   private String servers;
   private int poolSize;
   private long opTimeout;
}

这个时候在配置类中就可以进行使用

java 复制代码
@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;
    }
}

在服务类中注入使用

java 复制代码
@Autowired
private MemcachedClient memcachedClient;
public String sendCodeTosms(String tele){
memcachedclient.set(tele,0,code); //第一个参数是key,第二个参数是过期时间,第三个参数是值,这句话需要try-catch抛出
}

jetcache缓存供应商

jetCache对SpringCache进行了封装,在原有功能基础上实现了多级缓存,缓存统计,自动刷新,异步调用,数据报表等功能

jetCache设定了本地缓存与远程缓存的多级缓存解决方案

本地缓存:(local)

  1. LinkedHashMap
  2. Caffeine
    远程缓存:(remote)
  3. Redis
  4. Tair

jetcache的基本使用

设置外部服务

首先先导入依赖:

java 复制代码
        <dependency>
            <groupId>com.alicp.jetcache</groupId>
            <artifactId>jetcache-starter-redis</artifactId>
            <version>2.6.2</version>
        </dependency>

在配置文件中配置jetcache:

jetcache与spring是同一级别的配置

yml 复制代码
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启用缓存开关

java 复制代码
@springbootApplication
@EnableCreateCacheAnnotation
public class SpringbootApplication{
}

自定义缓存空间

java 复制代码
//注解第一个属性相当于值前的前缀,expire设置过期时间,3600默认单位秒,可以通过第三个参数设置单位
@CreateCache(name="jetcache",expire=3600,timeUnit=TimeUnit.SECONDS)
//自定义缓存空间,泛型中对应的是key和value的值
private Cache<String,String> jetcache;

存入缓存:

java 复制代码
jetcache.put("tele",code);

读取缓存:

java 复制代码
jetcache.get();
  • 切换管理模式

在配置中配置第二个管理模式sms如上所讲,那要如何进行切换

java 复制代码
@CreateCache(area="sms",name="",expire=)

通过注解进行管理模式的切换,这样命名空间就会用对应的管理模式进行创建空间

设置本地服务

同样在配置文件中进行配置:

yml 复制代码
jetcache:
  local:
    default:
       type: linkedhashmap
       keyConvertor: fastjson
       limit: #缓存的数据量
       

通过注解实现本地远程进行切换:

java 复制代码
@CreateCache(name="",expire=,cacheType=Cache.LOCAL)//有三个值可以进行切换
  • jetcache配置属性信息

jetcache方法缓存

如果需要启动方法缓存需要在启动类上面加入方法缓存的注解

java 复制代码
@springbootApplication
@EnableCreateCacheAnnotation
@EnableMethodCache(basepackages="包名")   //注解中的属性需要添加一个包名,所要添加注解的方法就在这个包下
public class SpringBootCacheApplicaton{
}

在方法上使用注解 @Cached进行缓存处理:

java 复制代码
@Cached(name="jetcache_",key="#id",expire=3600)
public Book getbyId(Integer id){
 return bookDao.getByid(id);
}
  • @Cached@CreateCache的区别:
  1. 用途: @CreateCache 用于创建和直接操作缓存实例;@Cached 用于自动处理方法返回值的缓存。
  2. 操作: 使用 @CreateCache 时,开发者需要手动从缓存中获取和存储数据;而 @Cached 则自动化这个过程,使得方法执行与缓存透明化。
  3. 灵活性: @CreateCache 提供更多的控制权和灵活性,因为您可以直接操作缓存;@Cached 更简单易用,适合那些希望自动缓存方法返回结果的场景。

注意前面提到的jecache配置文件中的配置:keyConvertor:fastjson

我们提到它可以将java对象数据转换为json格式的字符串存储在缓存当中,而jetcache缓存底层通过序列化与反序列化的机制进行转换,这时我们首先应该将实体类对象序列化,这样才能够将序列化后的java对象数据进行转换:

java 复制代码
@Data
public class Book implements Serializable{
   private Integer id;
   private String name;
}

接着进行操作:如果此时我们进行更新操作,此时缓存中的对应数据需要同步进行更新,那么此时,我们在进行更新操作的时候可以通过注解 @Cacheupdate同步进行更新操作:

java 复制代码
@Cacheupdate(name="book_",key="#book.id",value="#book")
public boolean update(Book book){
return bookDao.updayeById(book)>0;
}

同时在进行删除操作的时候也应该通过注解 @CacheInvalidate在缓存中进行同步操作:

java 复制代码
@CacheInvalidate(name="book_",key="#id")
public boolean delete(Integer id){
return bookDao.delete(id)>0;
}

通过以上三个操作就会显示出来一个问题,当多个用户同时操作一个数据的时候,可能会出现B用户操作后缓存同步完毕,A用户操作之后缓存没有进行同步看到的还是之前存在的数据这时就会出错:

我们可以通过注解 @CacheRefresh进行定时刷新,刷新缓存数据

java 复制代码
@Cached(...)
@CacheRefresh(refresh=10)

jetcache对应的操作信息可以通过配置进行查看:

yml 复制代码
jetcache:
   statIntervalMinutes: 1 #等待一分钟将一分钟内对缓存的操作进行分析统计并输出在控制台上

j2cache

j2cache 是一个缓存整合框架,可以提供缓存的整合方案,使各种缓存搭配使用,自身不提供缓存功能

这里我们基于 encache + redis 进行整合讲解j2cache

第一步导入依赖:

java 复制代码
<!--在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>

然后在配置文件中进行配置:

yml 复制代码
server:
  port: 80
j2cache:
  config-location: j2cache.properties

j2cache的配置文件是properties类型,在配置文件当中配置多级缓存

xml 复制代码
# 一级缓存
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:

java 复制代码
//定义一个缓存对象
@Autowired
private CacheChannel cacheChannel;
//在方法中使用该对象进行缓存的处理
cacheChannel.set("sms",tele,code);
String code=cacheChannel.get("sms",smsCode.getTele()).asString();//将我们的值变化为String类型的值 
相关推荐
不灭锦鲤9 分钟前
ssrf学习(ctfhub靶场)
网络·学习·安全
alfiy13 分钟前
Elasticsearch学习笔记(五)Elastic stack安全配置二
笔记·学习·elasticsearch
权^19 分钟前
MySQL--聚合查询、联合查询、子查询、合并查询(上万字超详解!!!)
大数据·数据库·学习·mysql
wclass-zhengge19 分钟前
Redis篇(最佳实践)(持续更新迭代)
redis·缓存·bootstrap
冷静 包容25 分钟前
C语言学习之 没有重复项数字的全排列
c语言·开发语言·学习
K3njuan41 分钟前
《数据结构》学习系列
学习
Dylanioucn42 分钟前
【分布式微服务云原生】探索Redis:数据结构的艺术与科学
数据结构·redis·分布式·缓存·中间件
结衣结衣.43 分钟前
C++ 类和对象的初步介绍
java·开发语言·数据结构·c++·笔记·学习·算法
Code成立1 小时前
1、深入理解Redis线程模型
数据库·redis·bootstrap
limengshi1383923 小时前
通信工程学习:什么是RIP路由信息协议
网络·网络协议·学习·智能路由器·信息与通信