---恢复内容开始---
单点缓存框架 只能针对单个jvm中,缓存容器存放jvm中,每个缓存互不影响 Ehcache gauva chache 内置缓存框架 jvm缓存框架
分布式缓存框架(共享缓存数据) Redis Meacache
example:
mybatis、hibernate地城都使用了Ehcache
Ehcache是纯java的开源缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。它主要面向通用缓存、Java EE和轻量级容器,具有内存和磁盘存储、缓存加载器、缓存扩展、缓存异常处理程序。
Ehcache最初由Greg Luck于2003年开始开发。2009年,该项目被Terracotta购买。软件仍然开源,但一些新的主要功能(例如,快速可重启性之间的一致性的)只能在商业产品中使用。
Ehcache 被广泛用于在Hibernate、Spring、Cocoon等其他开源系统。
1.快速;
2.简单;
3.多种缓存策略;
4.缓存数据有两级:内存和磁盘,因此无需担心容量问题;
5.缓存数据会在虚拟机重启的过程中写入磁盘;
6.可以通过 RMI、可插入 API 等方式进行分布式缓存;
7.具有缓存和缓存管理器的侦听接口;(为了做集群)
8.支持多缓存管理器实例,以及一个实例的多个缓存区域;
9.提供 Hibernate 的缓存实现;
Ehcache是用来管理缓存的一个工具,其缓存的数据可以是存放在内存里面的,也可以是存放在硬盘上的。其核心是CacheManager,一切Ehcache的应用都是从CacheManager开始的。它是用来管理Cache(缓存)的,一个应用可以有多个CacheManager,而一个CacheManager下又可以有多个Cache。Cache内部保存的是一个个的Element,而一个Element中保存的是一个key和value的配对,相当于Map里面的一个Entry。
(操作系统里面就有呀~)
当缓存需要被清理时(比如空间占用已经接近临界值了),需要使用某种淘汰算法来决定清理掉哪些数据。常用的淘汰算法有下面几种:
FIFO:First In First Out,先进先出。判断被存储的时间,离目前最远的数据优先被淘汰。
LRU:Least Recently Used,最近最少使用。判断最近被使用的时间,目前最远的数据优先被淘汰。(默认)
LFU:Least Frequently Used,最不经常使用。在一段时间内,数据被使用次数最少的,优先被淘汰。
缓存是容器存放在内存中,为了保证持久化机制,将缓存中的值持久化到硬盘上(日志缓存文件格式)。否则服务器重启 就没了哦
缓存框架都是支持对内存和硬盘支持
JVM内置缓存实现 (为了减轻数据库访问压力)
内存吃不愁销,限制而容量大小,会有相应的算法处理机制。
废话不多说,上项目Spring Boot 整合EhCache:
目录结构:
pom的的本相关依赖:
这样引入了 就可以为所欲为了 Ehcache底层也是用Map集合实现的
jar+mapper层的注解+启动类的注解+配置文件+application.yml指定加载的缓配置文件
pom:
4.0.0
com.toov5.architect
architect
0.0.1-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
2.0.0.RELEASE
org.projectlombok
lombok
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-tomcat
org.apache.tomcat.embed
tomcat-embed-jasper
org.springframework.boot
spring-boot-starter-log4j
1.3.8.RELEASE
org.springframework.boot
spring-boot-starter-aop
commons-lang
commons-lang
2.6
org.apache.httpcomponents
httpclient
com.alibaba
fastjson
1.2.47
javax.servlet
jstl
taglibs
standard
1.1.2
org.springframework.boot
spring-boot-starter-cache
net.sf.ehcache
ehcache
2.9.1
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.1.1
mysql
mysql-connector-java
实体类:
package com.toov5.entity;
import lombok.Data;
@Data
public class Users {
private String name;
private Integer age;
}
controller
package com.toov5.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.toov5.entity.Users;
import com.toov5.service.UserService;
@RestController
public class IndexController {
@Autowired
private UserService userService;
@RequestMapping("/getUser")
public List getUser(Long id){
return userService.getUser(id);
}
}
service
package com.toov5.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.toov5.entity.Users;
import com.toov5.mapper.UserMapper;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public List getUser(Long id){
return userMapper.getUser(id);
}
}
mapper
package com.toov5.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import com.toov5.entity.Users;
//引入的jar包后就有了这个注解了 非常好用 (配置缓存的基本信息)
@CacheConfig(cacheNames={"userCache"}) //缓存的名字 整个类的
public interface UserMapper {
@Select("SELECT ID ,NAME,AGE FROM users where id=#{id}")
@Cacheable //让这个方法实现缓存 查询完毕后 存入到缓存中 不是每个方法都需要缓存呀!save()就不用了吧
List getUser(@Param("id") Long id);
}
启动类:
package com.toov5.app;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@EnableCaching //开启缓存
@MapperScan(basePackages={"com.toov5.mapper"})
@SpringBootApplication(scanBasePackages={"com.toov5.*"})
public class app {
public static void main(String[] args) {
SpringApplication.run(app.class, args);
}
}
配置文件:
###端口号配置
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
修改数据库的值
再次加载
注:配置文件相关信息
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。
解决缓存与DB同步问题
1、重启服务,jvm也会关闭重启
2、主动通知或者定时Job
场景 update 或者delete 容易造成缓存和DB不同步问题
update语句后 加上通知 主动通知 先修改成功 然后清理缓存 都是在同一个事务中的哟 定时Job健康检查 检查DB和缓存是否一致 然后执行清理缓存
controller加入清缓存的逻辑;
package com.toov5.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.toov5.entity.Users;
import com.toov5.service.UserService;
@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 getUser(Long id){
return userService.getUser(id);
}
}
执行查询后
修改数据库:
刷新页面不变,此时调用清理缓存
再次查询
好了 成功清理!