缓存技术

智能车图像处理19-进阶篇11--斜入十字补线 这篇文章主要讲述智能车竞赛中如何对于斜入十字进行补线操作。 阅读详情

聊聊缓存:

  • 缓存最终的目的是为减轻服务端压力,减少网络传输请求 比如: 浏览器访问自带缓存。 App客户端底层都有缓存技术的。
    注: (移动端登录 用token 本地是有个文件的)

案例:

如果一旦请求到服务器端之后,会在本地缓存一份,快速响应给用户。

常见的缓存方案:

  • 网络缓存
  • 代理缓存(Nginx可以缓存)
  • CDN缓存
  • 服务器缓存
  • 数据库缓存
  • 平台缓存级缓存

总结: 缓存最终的目的是为减轻服务端压力,减少网络传输请求

单机缓存与分布式缓存:
  • Session 是存放在服务器端(保存在单个JVM中),返回SessionId(响应头),客户端存放的SessionId,下次请求时候,直接使用对于的SessionId从服务器端查询对应Session

  • 分布式Session (Session共享的问题)----直接使用token解决


案例单机版: 实现单个JVM缓存框架, Session Key Value 可以用Map集合实现 过期时间需要好好设计了 写一个给予Map集合实现Jvm缓存框架:

首先定义map实现的缓存类:(concurrentHashmap保证安全)

缓存:

@Component  //这样的话 就是单例的了!!!注入到容器里面 
public class MapCache<K,V> {
    //存放缓存容器
   public ConcurrentHashMap<K, V> concurrentHashMap = new ConcurrentHashMap<K,V>();
    //纯手写单个JVM缓存框架 缓存概念偏向于临时
    
   //对传统的Map包装
   public void put(K key,V value){
       concurrentHashMap.put(key, value);
   }
   //查询
   public V get(K key){
       return concurrentHashMap.get(key);
   }
   
   public void remove(String k){
       //这个map是安全的 不需要加锁!
       concurrentHashMap.remove(k);
   }
}

controller类:

@RestController
public class IndexController {
  
    @Autowired
    private MapCache<String, Object> mapCache;
    
    @RequestMapping("/get")
    public String get(String key){
        return (String)mapCache.get(key);
    }
    
    @RequestMapping("/put")
    public String put(String key, String value){
        mapCache.put(key, value);
        return "成功";
    }
    
    @RequestMapping("/remove")
    public String remove(String key){
        mapCache.remove(key);
        return "成功";
    }

}

启动类

@SpringBootApplication(scanBasePackages={"com.toov5.*"})
public class app {
   public static void main(String[] args) {
    SpringApplication.run(app.class, args);
}
    
}

 

单机版缓存框架

  • 单点缓存框架 只能针对单个jvm中,缓存容器存放jvm中,每个缓存互不影响 Ehcache gauva chache 内置缓存框架 jvm缓存框架

  • 分布式缓存技术(共享缓存数据) Redis Meacache

example:

mybatis、hibernate底层都使用了Ehcache

本地缓存Ehcache 什么是Ehcache  Ehcache是纯java的开源缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。它主要面向通用缓存、Java EE和轻量级容器,具有内存和磁盘存储、缓存加载器、缓存扩展、缓存异常处理程序。

Ehcache最初由Greg Luck于2003年开始开发。2009年,该项目被Terracotta购买。软件仍然开源,但一些新的主要功能(例如,快速可重启性之间的一致性的)只能在商业产品中使用。

Ehcache 被广泛用于在Hibernate、Spring、Cocoon等其他开源系统。

Ehcache的主要特性 1.快速;

2.简单;

3.多种缓存策略;

4.缓存数据有两级:内存和磁盘,因此无需担心容量问题;

5.缓存数据会在虚拟机重启的过程中写入磁盘;

6.可以通过 RMI、可插入 API 等方式进行分布式缓存;

7.具有缓存和缓存管理器的侦听接口;(为了做集群)

8.支持多缓存管理器实例,以及一个实例的多个缓存区域;

9.提供 Hibernate 的缓存实现;

Ehcache使用介绍

Ehcache是用来管理缓存的一个工具,其缓存的数据可以是存放在内存里面的,也可以是存放在硬盘上的。其核心是CacheManager,一切Ehcache的应用都是从CacheManager开始的。它是用来管理Cache(缓存)的,一个应用可以有多个CacheManager,而一个CacheManager下又可以有多个Cache。Cache内部保存的是一个个的Element,而一个Element中保存的是一个key和value的配对,相当于Map里面的一个Entry。

  • Ehcache缓存过期策略 (操作系统里面就有呀~)

  • 当缓存需要被清理时(比如空间占用已经接近临界值了),需要使用某种淘汰算法来决定清理掉哪些数据。常用的淘汰算法有下面几种:

FIFO:First In First Out,先进先出。判断被存储的时间,离目前最远的数据优先被淘汰。

LRU:Least Recently Used,最近最少使用。判断最近被使用的时间,目前最远的数据优先被淘汰。(默认)

LFU:Least Frequently Used,最不经常使用。在一段时间内,数据被使用次数最少的,优先被淘汰。

注意:

  • 缓存是容器存放在内存中,为了保证持久化机制,将缓存中的值持久化到硬盘上(日志缓存文件格式)。否则服务器重启 就没了哦!
  • 缓存框架都是支持对内存和硬盘支持
  • JVM内置缓存实现 (为了减轻数据库访问压力)
  • 内存吃不愁销,限制而容量大小,会有相应的算法处理机制。


单机版缓存框架

  • 单点缓存框架 只能针对单个jvm中,缓存容器存放jvm中,每个缓存互不影响 Ehcache gauva chache 内置缓存框架 jvm缓存框架

  • 分布式缓存技术(共享缓存数据) Redis Meacache

example:

mybatis、hibernate底层都使用了Ehcache

本地缓存Ehcache 什么是Ehcache  Ehcache是纯java的开源缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。它主要面向通用缓存、Java EE和轻量级容器,具有内存和磁盘存储、缓存加载器、缓存扩展、缓存异常处理程序。

Ehcache最初由Greg Luck于2003年开始开发。2009年,该项目被Terracotta购买。软件仍然开源,但一些新的主要功能(例如,快速可重启性之间的一致性的)只能在商业产品中使用。

Ehcache 被广泛用于在Hibernate、Spring、Cocoon等其他开源系统。

Ehcache的主要特性 1.快速;

2.简单;

3.多种缓存策略;

4.缓存数据有两级:内存和磁盘,因此无需担心容量问题;

5.缓存数据会在虚拟机重启的过程中写入磁盘;

6.可以通过 RMI、可插入 API 等方式进行分布式缓存;

7.具有缓存和缓存管理器的侦听接口;(为了做集群)

8.支持多缓存管理器实例,以及一个实例的多个缓存区域;

9.提供 Hibernate 的缓存实现;

Ehcache使用介绍

Ehcache是用来管理缓存的一个工具,其缓存的数据可以是存放在内存里面的,也可以是存放在硬盘上的。其核心是CacheManager,一切Ehcache的应用都是从CacheManager开始的。它是用来管理Cache(缓存)的,一个应用可以有多个CacheManager,而一个CacheManager下又可以有多个Cache。Cache内部保存的是一个个的Element,而一个Element中保存的是一个key和value的配对,相当于Map里面的一个Entry。

  • Ehcache缓存过期策略 (操作系统里面就有呀~)

  • 当缓存需要被清理时(比如空间占用已经接近临界值了),需要使用某种淘汰算法来决定清理掉哪些数据。常用的淘汰算法有下面几种:

FIFO:First In First Out,先进先出。判断被存储的时间,离目前最远的数据优先被淘汰。

LRU:Least Recently Used,最近最少使用。判断最近被使用的时间,目前最远的数据优先被淘汰。(默认)

LFU:Least Frequently Used,最不经常使用。在一段时间内,数据被使用次数最少的,优先被淘汰。

注意:

  • 缓存是容器存放在内存中,为了保证持久化机制,将缓存中的值持久化到硬盘上(日志缓存文件格式)。否则服务器重启 就没了哦!
  • 缓存框架都是支持对内存和硬盘支持
  • JVM内置缓存实现 (为了减轻数据库访问压力)
  • 内存吃不愁销,限制而容量大小,会有相应的算法处理机制。

Spring Boot 整合EhCache: 

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.toov5.architect</groupId>
  <artifactId>architect</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.RELEASE</version>
    </parent>
    <dependencies>
        <!-- SpringBoot 对lombok 支持 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- SpringBoot web 核心组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
        <!-- SpringBoot 外部tomcat支持 -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
        </dependency>
        <!-- springboot-log4j -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j</artifactId>
            <version>1.3.8.RELEASE</version>
        </dependency>
        <!-- springboot-aop 技术 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
        <!--开启 cache 缓存 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <!-- ehcache缓存 -->
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>2.9.1</version><!--$NO-MVN-MAN-VER$ -->
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>
        <!-- mysql 依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    </dependencies>
  
</project>

实体类:

@Data
public class Users {
  private String name;
  private Integer age;
}

controller:

@RestController
public class IndexController {
      
    @Autowired
    private UserService userService;
    
    @RequestMapping("/getUser")
    public List<Users> getUser(Long id){
        return userService.getUser(id);
    }

}

Service

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    
   public List<Users> getUser(Long id){
       return userMapper.getUser(id);
   }
}

Mapper:

//引入的jar包后就有了这个注解了 非常好用 (配置缓存的基本信息)
@CacheConfig(cacheNames={"userCache"})  //缓存的名字  整个类的
public interface UserMapper {
    @Select("SELECT ID ,NAME,AGE FROM users where id=#{id}")
    @Cacheable //让这个方法实现缓存 查询完毕后 存入到缓存中  不是每个方法都需要缓存呀!save()就不用了吧
    List<Users> getUser(@Param("id") Long id);
}

EhCache配置:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
 
    <diskStore path="java.io.tmpdir/ehcache-rmi-4000" />
 
 
    <!-- 默认缓存 -->
    <defaultCache maxElementsInMemory="1000" eternal="true"
        timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
        diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000"
        diskPersistent="true" diskExpiryThreadIntervalSeconds="120"
        memoryStoreEvictionPolicy="LRU">
    </defaultCache>
   
    <!-- demo缓存 --><!-- name="userCache" 对应我们在 @CacheConfig(cacheNames={"userCache"}) !!!!! -->
    <!--Ehcache底层也是用Map集合实现的 -->
    <cache name="userCache" maxElementsInMemory="1000" eternal="false"
        timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
        diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000"
        diskPersistent="false" diskExpiryThreadIntervalSeconds="120"
        memoryStoreEvictionPolicy="LRU">  <!-- LRU缓存策略 -->
        <cacheEventListenerFactory
            class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" />
        <!-- 用于在初始化缓存,以及自动设置 -->
        <bootstrapCacheLoaderFactory
            class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory" />
    </cache>
</ehcache>

yml:

###端口号配置
server:
  port: 8080
###数据库配置 
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
    test-while-idle: true
    test-on-borrow: true
    validation-query: SELECT 1 FROM DUAL
    time-between-eviction-runs-millis: 300000
    min-evictable-idle-time-millis: 1800000
# 缓存配置读取
  cache:
    type: ehcache
    ehcache:
      config: classpath:app1_ehcache.xml 

启动:

@EnableCaching //开启缓存
@MapperScan(basePackages={"com.toov5.mapper"})
@SpringBootApplication(scanBasePackages={"com.toov5.*"})
public class app {
   public static void main(String[] args) {
    SpringApplication.run(app.class, args);
}
    
}

项目结构:

访问:

备注介绍:【EhCache参数相关】

1. diskStore :指定数据(.data and .index)存储位置,可指定磁盘中的文件夹位置期 The diskStore element is optional. It must be configured if you have overflowToDisk or diskPersistent enabled    for any cache. If it is not configured, a warning will be issues and java.io.tmpdir will be used.
2. defaultCache : 默认的管理策略
Ehcache 使用Map集合实现的 element 其实就是 key 和value

一、以下属性是必须的:

  1、name: Cache的名称,必须是唯一的(ehcache会把这个cache放到HashMap里)。

  2、maxElementsInMemory:在内存中缓存的element的最大数目。

  3、maxElementsOnDisk:在磁盘上缓存的element的最大数目,默认值为0,表示不限制。

  4、eternal:设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断。

  5、overflowToDisk: 如果内存中数据超过内存限制,是否要缓存到磁盘上。

二、以下属性是可选的:

  1、timeToIdleSeconds: 对象空闲时间,指对象在多长时间没有被访问就会失效。只对eternal为false的有效。默认值0,表示一直可以访问。

  2、timeToLiveSeconds: 对象存活时间,指对象从创建到失效所需要的时间。只对eternal为false的有效。默认值0,表示一直可以访问。

  3、diskPersistent: 是否在磁盘上持久化。指重启jvm后,数据是否有效。默认为false。

  4、diskExpiryThreadIntervalSeconds: 对象检测线程运行时间间隔。标识对象状态的线程多长时间运行一次。

  5、diskSpoolBufferSizeMB: DiskStore使用的磁盘大小,默认值30MB。每个cache使用各自的DiskStore。

  6、memoryStoreEvictionPolicy: 如果内存中数据超过内存限制,向磁盘缓存时的策略。默认值LRU,可选FIFO、LFU。EhCache同步DB: 
场景描述:
update 或者delete 容易造成缓存和DB不同步问题   

解决方案:

    • 主动通知或者定时Job
    • update语句后,加上通知,进行主动通知
    • 先修改成功 然后清理缓存。【都是在同一个事务中的】
    • 定时Job健康检查,检查DB和缓存是否一致。然后决定执行清理缓存
@RestController
public class IndexController {
    @Autowired
    private CacheManager cacheManager;
    @Autowired
    private UserService userService;
    //注意引入的jar包是 org.springframework.cache.CacheManager;
    @RequestMapping("/remoKey")
    public void remoKey() {
        cacheManager.getCache("userCache").clear();  //传入名字 进行清除
    }
    
    @RequestMapping("/getUser")
    public List<Users> getUser(Long id){
        return userService.getUser(id);
    }

}

1.访问:

2.修改数据

3.手动清理缓存,接口调用

4.访问:


分布式缓存

EhCache+Redis实现分布式缓存

Ehcache集群模式介绍

由于 EhCache 是进程中的缓存系统,一旦将应用部署在集群环境中,每一个节点维护各自的缓存数据,当某个节点对缓存数据进行更新,这些更新的数据无法在其它节点中共享,这不仅会降低节点运行的效率,而且会导致数据不同步的情况发生。例如某个网站采用 A、B 两个节点作为集群部署,当 A 节点的缓存更新后,而 B 节点缓存尚未更新就可能出现用户在浏览页面的时候,一会是更新后的数据,一会是尚未更新的数据,尽管我们也可以通过 Session Sticky 技术来将用户锁定在某个节点上,但对于一些交互性比较强或者是非 Web 方式的系统来说,Session Sticky 显然不太适合。

EhCache常用集群模式

EhCache从1.7版本开始,支持五种集群方案,分别是:

  • Terracotta
  • RMI
RMi集群模式
你如何知道集群环境中的其他缓存?

• 分布式传送的消息是什么形式?

• 什么情况需要进行复制?增加(Puts),更新(Updates)或是失效(Expiries)?

• 采用什么方式进行复制?同步还是异步方式?

 
1、正确的元素类型:只有可序列化的元素可以进行复制。一些操作,比如移除,只需要元素的键值而不用整个元素;在这样的操作中即使元素不是可序列化的但键值是可序列化的也可以被复制。

2、成员发现(Peer Discovery):Ehcache进行集群的时候有一个cache组的概念。每个cache都是其他cache的一个peer,没有主cache的存在。成员发现(Peer Discovery)正是用来解决 “你如何知道集群环境中的其他缓存?” 这个问题的。Ehcache提供了两种机制用来进行成员发现,即:自动成员发现和手动成员发现。要使用一个内置的成员发现机制要在ehcache的配置文件中指定cacheManagerPeerProviderFactory元素的class属性为

net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory。
  • JMS
  • JGroups
  • EhCache Server

Ehcache的使用场景

  • 使用纯java的ehcache作为本地缓存
  • Reids 作为远程分布式缓存
  • 解决redis缓存压力过大,提高缓存速度,以及缓存性能。

Redis和Ehcache缓存的区别

  • 如果是单个应用或者对缓存访问要求很高的应用,用EhCache。
  • 如果是大型系统,存在缓存共享、分布式部署、缓存内容很大的,建议用redis。
  • EHCache适合单体项目缓存,不适合于分布式。(不支持共享),因为他们存放在JVM中,互不影响。
  • 分布式缓存架构中,使用Redis+EHCache实现分布式缓存。分布式 一级、二级缓存。 比如: 如果Redis集群 因为 某些原因 全部宕机 。 客户端会一直查询数据库!
  • Redis支持分布式共享查询

注: EhCache支持分布式缓存 但是不推荐

EhCache实际使用场景总结:

  1. 我们在项目中使用集中式缓存(Redis或者式Memcached等),通常都是检查缓存中是否存在期望值的数据,如果存在直接返回,如果不存在就查询数据库让后在将数据库缓存,这个时候如果缓存系统因为某写原因宕机,造成服务无法访问,那么大的量请求直接穿透到数据库,最数据库压力非常大。这时候我们让ehcache作为二级缓存,当redis服务器宕机后,可以查询ehcache缓存。 这样能够有效的扛住服务器请求压力。

分布式缓存图 :


Spring Boot2.0+Redis+Ehcache实现二级缓存

前言:

  • 先走本地,本地没有再走网络 尽量少走Redis 效率会高一些
  • Ehchache 不需要走网络,直接从内存中获取.由于Ehchache容器限制,会持久化在硬盘上。

实现:

  • spring boot中集成了spring cache,并有多种缓存方式的实现,如:Redis、Caffeine、JCache、EhCache等等。但如果只用一种缓存,要么会有较大的网络消耗(如Redis),要么就是内存占用太大(如Caffeine这种应用内存缓存)。在很多场景下,可以结合起来实现一、二级缓存的方式,能够很大程度提高应用的处理效率。

  • spring cache:主要包含spring cache定义的接口方法说明和注解中的属性说明

补充: 缓存、两级缓存

简单的理解,缓存就是将数据从读取较慢的介质上读取出来放到读取较快的介质上,如磁盘-->内存。平时我们会将数据存储到磁盘上,如:数据库。如果每次都从数据库里去读取,会因为磁盘本身的IO影响读取速度,所以就有了像redis这种的内存缓存。可以将数据读取出来放到内存里,这样当需要获取数据时,就能够直接从内存中拿到数据返回,能够很大程度的提高速度。但是一般redis是单独部署成集群,所以会有网络IO上的消耗,虽然与redis集群的链接已经有连接池这种工具,但是数据传输上也还是会有一定消耗。所以就有了应用内缓存,如:caffeine。当应用内缓存有符合条件的数据时,就可以直接使用,而不用通过网络到redis中去获取,这样就形成了两级缓存。应用内缓存叫做一级缓存,远程缓存(如redis)叫做二级缓存 

spring boot + spring cache 实现两级缓存(redis + caffeine)代码实现:

实体类:

@Data
public class Users implements Serializable{
  private String name;
  private Integer age;
}

controller

@RestController
public class IndexController {
    @Autowired
    private UserService userService;
    
    @RequestMapping("/userId")
    public Users getUserId(Long id){
        return userService.getUser(id);  
    }

}

Service

@Component
public class EhCacheUtils {

    // @Autowired
    // private CacheManager cacheManager;
    @Autowired
    private EhCacheCacheManager ehCacheCacheManager;

    // 添加本地缓存 (相同的key 会直接覆盖)
    public void put(String cacheName, String key, Object value) {
        Cache cache = ehCacheCacheManager.getCacheManager().getCache(cacheName);
        Element element = new Element(key, value);
        cache.put(element);
    }

    // 获取本地缓存
    public Object get(String cacheName, String key) {
        Cache cache = ehCacheCacheManager.getCacheManager().getCache(cacheName);
        Element element = cache.get(key);
        return element == null ? null : element.getObjectValue();
    }

    public void remove(String cacheName, String key) {
        Cache cache = ehCacheCacheManager.getCacheManager().getCache(cacheName);
        cache.remove(key);
    }

}
@Component
public class RedisService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    //这样该方法支持多种数据类型 
    public void set(String key , Object object, Long time){
        //开启事务权限
        stringRedisTemplate.setEnableTransactionSupport(true);
        try {
            //开启事务
            stringRedisTemplate.multi();
            
            String argString =(String)object;  //强转下
            stringRedisTemplate.opsForValue().set(key, argString);
            
            //成功就提交
            stringRedisTemplate.exec();
        } catch (Exception e) {
            //失败了就回滚
            stringRedisTemplate.discard();
            
        }
        if (object instanceof String ) {  //判断下是String类型不
            String argString =(String)object;  //强转下
            //存放String类型的
            stringRedisTemplate.opsForValue().set(key, argString);
        }
        //如果存放Set类型
        if (object instanceof Set) {
            Set<String> valueSet =(Set<String>)object;
            for(String string:valueSet){
                stringRedisTemplate.opsForSet().add(key, string);  //此处点击下源码看下 第二个参数可以放好多
            }
        }
        //设置有效期
        if (time != null) {
            stringRedisTemplate.expire(key, time, TimeUnit.SECONDS);
        }
        
    }
    //做个封装
    public void setString(String key, Object object){
        String argString =(String)object;  //强转下
        //存放String类型的
        stringRedisTemplate.opsForValue().set(key, argString);
    }
    public void setSet(String key, Object object){
        Set<String> valueSet =(Set<String>)object;
        for(String string:valueSet){
            stringRedisTemplate.opsForSet().add(key, string);  //此处点击下源码看下 第二个参数可以放好多
        }
    }
    
    public String getString(String key){
     return    stringRedisTemplate.opsForValue().get(key);
    }
    
    
}
@Component
public class UserService {
    @Autowired
    private EhCacheUtils ehCacheUtils;
    @Autowired
    private RedisService redisService;
    @Autowired
    private UserMapper userMapper;
    //定义个全局的cache名字
    private String cachename ="userCache";
    
    public Users getUser(Long id){
        //先查询一级缓存  key以当前的类名+方法名+id+参数值
        String key = this.getClass().getName() + "-" + Thread.currentThread().getStackTrace()[1].getMethodName()
                + "-id:" + id;
        //查询一级缓存数据有对应值的存在 如果有 返回
        Users user = (Users)ehCacheUtils.get(cachename, key);
        if (user != null) {
            System.out.println("key"+key+",直接从一级缓存获取数据"+user.toString());
            return user;
        }
        //一级缓存没有对应的值存在,接着查询二级缓存    
        // redis存对象的方式  json格式 然后反序列号
        String userJson = redisService.getString(key);
        //如果rdis缓存中有这个对应的值,修改一级缓存    最下面的会有的 相同会覆盖的    
        if (!StringUtil.isNullOrEmpty(userJson)) {  //有 转成json
            JSONObject jsonObject = new JSONObject();//用的fastjson
            Users resultUser = jsonObject.parseObject(userJson,Users.class);
            ehCacheUtils.put(cachename, key, resultUser);
            return resultUser;
        }
        //都没有 查询DB 
        Users user1 = userMapper.getUser(id);
        if (user1 == null) {
            return null;
        }
        //存放到二级缓存 redis中
        redisService.setString(key, new JSONObject().toJSONString(user1));
        //存放到一级缓存 Ehchache
        ehCacheUtils.put(cachename, key, user1);
        return user1;
    }
}

启动类

@EnableCaching //开启缓存
@MapperScan(basePackages={"com.toov5.mapper"})
@SpringBootApplication(scanBasePackages={"com.toov5.*"})
public class app {
   public static void main(String[] args) {
    SpringApplication.run(app.class, args);
}
    
}

app1.ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
 
    <diskStore path="java.io.tmpdir/ehcache-rmi-4000" />
 
 
    <!-- 默认缓存 -->
    <defaultCache maxElementsInMemory="1000" eternal="true"
        timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
        diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000"
        diskPersistent="true" diskExpiryThreadIntervalSeconds="120"
        memoryStoreEvictionPolicy="LRU">
    </defaultCache>
   
    <!-- demo缓存 --><!-- name="userCache" 对应我们在 @CacheConfig(cacheNames={"userCache"}) !!!!! -->
    <!--Ehcache底层也是用Map集合实现的 -->
    <cache name="userCache" maxElementsInMemory="1000" eternal="false"
        timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
        diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000"
        diskPersistent="false" diskExpiryThreadIntervalSeconds="120"
        memoryStoreEvictionPolicy="LRU">  <!-- LRU缓存策略 -->
        <cacheEventListenerFactory
            class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" />
        <!-- 用于在初始化缓存,以及自动设置 -->
        <bootstrapCacheLoaderFactory
            class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory" />
    </cache>
</ehcache>

yml:

###端口号配置
server:
  port: 8080
###数据库配置 
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
    test-while-idle: true
    test-on-borrow: true
    validation-query: SELECT 1 FROM DUAL
    time-between-eviction-runs-millis: 300000
    min-evictable-idle-time-millis: 1800000
# 缓存配置读取
  cache:
    type: ehcache
    ehcache:
      config: classpath:app1_ehcache.xml
 
  redis:
    database: 0  
    host:  192.168.91.3
    port:  6379
    password:  123
    jedis:
      pool:
        max-active: 8
        max-wait: -1
        max-idle: 8
        min-idle: 0
    timeout: 10000

运行结果 

后面的访问,在控制台打印: 

代码一定要注意:

  • 一级缓存过期时间, 比二级要短一些。
  • 这里的两级缓存时间问题,执行设置二级缓存时候需要时间的,所以这两个时间设置问题一定要注意了。如下图: 

分布式缓存的思考:

  • 应用缓存: 缓存命中率、缓存回收策略 Java缓存类型、磁盘缓存
  • Http缓存: Http客户端缓存、 NginxHttp缓存设置、Nginx代理缓存
  • 多级缓存: 缓存数据、 分布式缓存与负载均衡、热点数据与更新缓存、缓存崩溃与快速修复
Autosar PWM模块的配置和使用 在上面的代码中,我们首先配置了PWM的初始化参数,包括频率和分辨率。GPIO Driver:由于PWM信号需要输出到特定的引脚上,因此我们还需要使用GPIO驱动程序来控制引脚的状态。通过合理配置和应用PWM模块,我们可以实现对汽车电子系统中各种功能的精确控制,从而提高汽车性能和用户体验。在实际应用中,我们可以根据需要进行更多的配置和调整,以实现灵活的PWM控制。PWM Driver:这是主要的PWM驱动程序,负责产生PWM信号并输出到相应的引脚上。接下来,我们需要配置PWM模块的参数。 阅读详情

相关推荐

手把手教你用树莓派蓝牙抓取小米温湿度计2代数据,接入HomeAssistant(附密钥获取避坑指南)

本文详细介绍了如何通过树莓派蓝牙抓取小米温湿度计2代数据并接入HomeAssistant的完整流程。重点解析了获取32位加密密钥的三种方法,包括使用Telink Flasher工具、米家APP抓包和开源工具ATC_MiThermometer,并提供了HomeAssistant集成配置和常见问题排查指南,帮助用户实现稳定可靠的温湿度监测。

一名菜鸟攻城师 779

关于Ehcache持久化缓存的一些见解

没有配置overflowToDisk属性前,达到最大缓存对象数目(即maxElementsInMemory后),ehcache会根据策略清理缓存,但是配置overflowToDisk属性后,缓存会得到保留,个人认为他是将缓存保存到磁盘上(但不是自己配置的目录,而是他的一个默认目录)想要将缓存持久化到磁盘,并且关闭服务器后下次打开可以继续使用上次的缓存,则必须要配置diskPersistent属性为true,才会将数据持久化到你配置的路径文件夹中(甚至不需要配置overflowToDisk)...

m0_56724799的博客 3476

WorkBuddy任务对话上下文管理:Token、compact与上下文窗口实战指南

在大语言模型应用中,Token作为文本处理的最小单位,直接决定上下文窗口的消耗速度,而上下文窗口则限定了单次对话可承载的信息总量。当对话超出窗口限制时,compact压缩机制会触发有损摘要,导致关键约束丢失或工具调用结果被稀释。合理管理上下文不仅能提升多步骤任务的稳定性,还能显著降低Token成本与响应延迟。在文档处理、代码开发、多步自动化等场景中,通过主动压缩、状态外置、分段喂入等策略,可有效避免任务后期遗忘、版本混乱等问题。本文围绕WorkBuddy的上下文管理机制,从Token与compact的底层原

weixin_29055699的博客 391

Ehcache 缓存(二)xml配置相关

如果没有配置ehcache.xml文件,ehcache-failsafe.xml将作为默认的ehcache配置。 1. a). diskStore(磁盘存储)元素是可选的。当你为任意缓存开启了overflowToDisk或者diskPersistent属性时,  它就必须配置。如果没配置,那么会出现提示信息并默认使用java.io.tmpdir作为存储地址;   diskStore只有一

jiangzhongwei_的博客 2431

计算光刻效率革命:为什么Hopkins模型比Abbe模型快?深入解析TCC的魔力

本文深入解析了计算光刻中Hopkins模型相比Abbe模型的效率优势,重点探讨了TCC(透射交叉系数)的工程智慧。通过预计算光学系统特性并复用TCC矩阵,Hopkins模型实现了数量级的加速,特别适用于复杂照明条件下的光刻仿真。文章详细介绍了TCC的物理意义、模态分解技术以及GPU并行计算等关键加速策略,为半导体制造中的光刻工艺优化提供了实用见解。

weixin_33364627的博客 389

ESP32+micro-ROS机器人开发实战:轻量级ROS2嵌入式集成

ROS2是现代机器人软件栈的核心框架,其基于DDS的分布式通信与QoS保障能力为多节点协同提供基础支撑;而micro-ROS作为专为微控制器优化的ROS2兼容中间件,解决了资源受限设备(如ESP32)接入ROS2生态的关键难题。其通过分层架构将DDS通信下沉至上位机Agent,使MCU仅需运行轻量Client,大幅降低内存开销(实测<180KB)并保留标准ROS2接口语义。该方案广泛应用于教育机器人、移动底盘、传感器节点等嵌入式场景,尤其适合基于ESP-IDF开发的Wi-Fi/BLE物联网机器人系统。本文以

weixin_29025501的博客 400

Ehcache配置参数简介

ehache 属性简洁

彻底拆分,一切可控! 1121

紫光同创FPGA中ADF网表文件的黑匣子封装与PDS环境实战指南

本文详细介绍了在紫光同创FPGA开发环境中使用ADF网表文件进行黑匣子封装的实战指南。通过PDS环境配置、加密ADF生成、黑匣子集成及验证调试等步骤,帮助开发者实现核心IP保护,同时保持设计性能。特别适用于需要模块级代码保护的企业级FPGA开发场景。

weixin_33725239的博客 341

EhCache参数及磁盘持久化加载

EhCache是不错的Java开源缓存模块,Cache的配置很灵活,官方提供的Cache配置方式有好几种。你可以通过声明配置、在xml中配置、在程序里配置或者调用构造方法时传入不同的参数。 你可以将Cache的配置从代码中剥离出来,也可以在使用运行时配置,所谓的运行时配置无非也就是在代码中配置。以下是运行时配置的好处: 1、在同一个地方配置所有的Cache,这样很容易管理Cache的内存和

codepython的专栏 8598

科研党必备!用Requests+BeautifulSoup升级版Nature爬虫(含PDF下载功能)

本文介绍了一套基于Python Requests和BeautifulSoup的Nature期刊智能爬虫系统,专为科研人员设计,可自动抓取论文标题、摘要及开放获取的PDF文档。系统采用模块化设计,包含请求管理、PDF检测和邮件通知等功能,确保高效合规地获取学术资源,提升科研效率。

weixin_29041767的博客 256

ROSTCM6软件下载及语义网络分析详细操作教程(附网盘链接)

ROSTCM6是武汉大学沈阳教授研发编码的国内目前唯一的以辅助人文社会科学研究的大型免费社会计算平台。该软件可以实现微博分析、聊天分析、全网分析、网站分析、浏览分析、分词、词频统计、英文词频统计、流量分析、聚类分析等一系列文本分析。

m0_64336780的博客 4万+

Ehcache磁盘缓存(.index文件 .data文件)解析

先展示下ehcache.xml的内容 很普通 overflowToDisk、diskPersistent都是设置的true。网上很多说法当overflowToDisk=‘true’,内存超出maxElementsInMemory才会磁盘化,其实是错的。 其实只要设置了overflowToDisk=‘true’,就会产生data文件(序列化),缓存就会磁盘化。data文件只要cache.put()方法就能生成,并不用cache.flush()。.index文件是指向data的索引,而且比如tomcat服务器

weixin_37253610的博客 1724

Windows原生环境配置Tensorflow使用GPU

本文讲解如何在Windows原生环境搭建可调用GPU设备进行计算的Tensorflow2.x环境。 区别于WSL,使用Windows原始环境作为开发环境。

天然玩家的博客 1499

缓存技术的详解

说起缓存相关技术,老多了, memcache、redis、squid、varnish、web cache、 CDN等等。缓存技术五花八门,但这些技术间有什么共性的地方,又有什么不同的地方呢?答案肯定是有的,这次为大家分享及整理一下缓存方面的技术,主要分为三个系列展开: 缓存随谈系列之一:数据库缓存 缓存随谈系列之二:静态缓存 缓存随谈系列之三:动态缓存   一、什么是数据库缓存    ...

菲宇运维 1万+

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

深入解析缓存技术

本文探讨了缓存技术的应用,包括其基本原理、更新机制、数据过期策略以及缓存可能引起的问题和解决方案。首先介绍了缓存缓存原理,然后深入探讨了三种主要的缓存更新机制:Cache Aside模式、Read/Write Through模式和Write Behind Caching,以及其优缺点和适用场景。接着,文章讨论了数据过期策略,包括LRU、FIFO和LFU算法,并通过Go语言代码实现。最后,文章分析了缓存可能带来的不一致性、大key、缓存雪崩、缓存穿透和缓存击穿等问题,并提出了相应的解决方案。

tatasix的博客 1488

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

【后端】浅析缓存技术

缓存技术通过在高速存储介质中暂存数据副本,显著提升数据访问速度和系统响应性能。在人工智能领域,AI缓存技术特别突出。它利用先进的算法和模型预测用户需求,将数据预加载到内存中,以减少推断时间并提升AI模型的实时性能。另外,Alluxio作为一种开源的分布式存储系统,能够通过将数据在内存中进行存储和管理,为大数据处理提供高速访问能力,从而加速数据访问和分析过程。这些缓存技术不仅在数据管理和应用性能优化中发挥关键作用,也在提升系统效率和用户体验方面具有重要意义。

wnm23的专栏 1796

缓存技术详谈—PHP缓存技术

一、引论PHP,一门最近几年兴起的web设计脚本语言,由于它的强大和可伸缩性,近几年来得到长足的发展,php相比传统的asp网站,在速度上有绝对的优势,想mssql转6万条数据php如需要40秒,asp不下2分钟.但是,由于网站的数据越来越多,我们渴求能更快速的调用数据,不必要每次都从数据库掉,我们可以从其他的地方,比方一个文件,或者某个内存地址,这就是php的缓存技术,也就是Cache技术.

mecoblog的专栏 895

PHP常用缓存技术

PHP中常用的缓存技术包括编译缓存和数据缓存两大类。编译缓存主要用于减少PHP代码的编译时间,提高执行效率;数据缓存则用于减少数据库的访问次数和计算量,提升性能。在实际应用中,可以根据项目的具体需求和性能要求来选择适合的缓存技术。同时,还需要注意缓存的粒度和有效期等设置,以确保缓存的有效性和一致性。

sheji888的专栏 1451

网页缓存技术

转自:https://www.cnblogs.com/firejava/p/6256788.html 网站技术高速发展的今天,缓存技术已经成为大型网站的一个关键技术,缓存设计好坏直接关系的一个网站访问的速度,以及购置服务器的数量,甚至影响到用户的体验。   网站缓存按照存放的地点不同,可以分为客户端缓存、服务端缓存。 客户端缓存   客户端缓存又可分为:浏览器缓存、网关或代理服务器...

weixin_30628801的博客 364

什么是缓存?常见的缓存技术有哪些?

缓存(Cache)是一种高速数据存储层,其核心目标是通过存储频繁访问的数据副本,减少对底层较慢存储介质(如内存、磁盘、网络)的直接访问,从而提升系统性能和响应速度。缓存技术基于局部性原理(时间局部性和空间局部性),即程序在一段时间内倾向于重复访问某些数据或邻近数据。硬件级缓存CPU缓存:位于CPU与主存之间,分为L1(一级)、L2(二级)、L3(三级)缓存,逐级容量增大但速度递减,用于缓解CPU与内存间的速度差异。

破损的天堂鸟博客 4090

常用的缓存技术都有哪些

• 术语:浏览器缓存策略(Browser Caching Policy)、缓存大小(Cache Size)、缓存生命周期(Cache Lifetime)。• 术语:缓存代理(Cache Proxy)、缓存失效(Cache Invalidation)、缓存同步(Cache Synchronization)。• 缓存命中(Cache Hit)、缓存未命中(Cache Miss)、缓存过期(Cache Expiration)。• 浏览器内部使用的缓存,用于存储网页、图像、脚本等资源,以提高网页加载速度。

weixin_57763462的博客 1393

介绍缓存的基本概念和常用的缓存技术

摘要: 介绍缓存的基本概念和常用的缓存技术,给出了各种技术的实现机制的简单介绍和适用范围说明,以及设计缓存方案应该考虑的问题(共17页)1         概念1.1   缓存能解决的问题· 性能——将相应数据存储起来以避免数据的重复创建、处理和传输,可有效提高性能。比如将不改变的数据缓存起来,例如国家列表等,这样能明显提高web程序的反应速度;· 稳定性——同一个应用中,对同一数据、逻辑功能和用

li_yu_hai的专栏 4万+

web缓存技术总结

1 web缓存的简介 1.1 采取Web加速技术措施  采取Web加速技术,减少用户访问的延迟。如采用Web缓存[8](Web Caching )技术、Web预取(Web Prefetching)技术、CDN ( Content Delivery Network)技术等,以此来降低用户可感知的网络访问延迟,提高网络服务质量。   典型的缓存体系结构有IRCache, Summary C

simon的天空 1万+

缓存的基本概念和常用的缓存技术

摘要: 介绍缓存的基本概念和常用的缓存技术,给出了各种技术的实现机制的简单介绍和适用范围说明,以及设计缓存方案应该考虑的问题(共17页)1         概念1.1   缓存能解决的问题· 性能——将相应数据存储起来以避免数据的重复创建、处理和传输,可有效提高性能。比如将不改变的数据缓存起来,例如国家列表等,这样能明显提高web程序的反应速度;· 稳定性——同一个应用中,对同一数据、逻辑功能和用...

杰哥一号号的博客 2万+

网站缓存技术

网站技术高速发展的今天,缓存技术已经成为大型网站的一个关键技术,缓存设计好坏直接关系的一个网站访问的速度,以及购置服务器的数量,甚至影响到用户的体验。   网站缓存按照存放的地点不同,可以分为客户端缓存、服务端缓存。     一、客户端缓存   客户端缓存又可分为:浏览器缓存、网关或代理服务器缓存。   1、网关或代理服务器缓存        网关或代理服务器缓存是将网

rongwenbin的专栏 845

php缓存技术实例,PHP的缓存技术

PHP,一门最近几年兴起的web设计脚本语言,由于它的强大和可伸缩性,近几年来得到长足的发展,php相比传统的asp网站,在速度上有绝对的优势,想mssql转6万条数据php如需要40秒,asp不下2分钟.但是,由于网站的数据越来越多,我们渴求能更快速的调用数据,不必要每次都从数据库掉,我们可以从其他的地方,比方一个文件,或者某个内存地址,这就是php的缓存技术,也就是Cache技术.二、分析深入...

weixin_39626298的博客 142

java缓存技术介绍

缓存一致性:在数据更新时,需要确保缓存中的数据与数据库中的数据保持一致。分布式缓存:数据存储在多个服务器的内存中,通过一定的机制(如哈希算法)实现数据的分布式存储和访问,适用于大型分布式系统。一个高性能的Java缓存库,由Ben-Manes开发,是Guava Cache的替代者,提供了更高的性能和更多的功能。Google提供的一个开源Java缓存库,提供了强大的缓存功能,包括自动加载、缓存回收、统计信息等。一个开源的Java分布式缓存框架,提供了丰富的缓存管理功能,支持内存和磁盘存储,以及分布式缓存。

weixin_57763462的博客 1328
上一篇: Map实现缓存
下一篇: 缓存框架Ehcache相关
Art&Code
博客等级 码龄7年 77粉丝 554原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值