缓存应用(一)Ehcache使用介绍
为什么要使用缓存
缓存的分类
客户端缓存
页面缓存
浏览器缓存
App客户端缓存
网络缓存
代理缓存
CDN缓存
服务器缓存
数据库缓存
平台缓存级缓存
缓存最终的目的是为减轻服务端压力,减少网络传输请求
基于Map集合实现本地缓存
定义Map缓存工具类
@Component public class MapEhcaChe<K, V> { private Map<K, V> ehcaCheMap = new ConcurrentHashMap<K, V>(); public void put(K k, V value) { ehcaCheMap.put(k, value); } public V get(K k) { return ehcaCheMap.get(k); } public void remove(K k) { ehcaCheMap.remove(k); } } |
使用案例
@RequestMapping("/ehcaChePut") public String put(String key, String value) { mapEhcaChe.put(key, value); return "success"; } @RequestMapping("/get") public String get(String key) { String value = mapEhcaChe.get(key); return value; } |
本地缓存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,最不经常使用。在一段时间内,数据被使用次数最少的,优先被淘汰。
Ehcache基本用法
SpringBoot2.0整合Ehcache框架
Maven环境依赖
<!-- caching -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- Ehcache 坐标 -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
配置文件信息 新增ehcache.xml文件
application文件配置
spring:cache:#ehcache配置文件路径ehcache:config: classpath:/ehcache.xml#指定缓存类型,可加可不加#type: ehcache
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<!--diskStore:为缓存路径,ehcache分为内存和磁盘 2级,此属性定义磁盘的缓存位置user.home - 用户主目录user.dir - 用户当前工作目录java.io.tmpdir - 默认临时文件路径-->
<diskStore path="java.io.tmpdir"/>
<!--defaultCache:echcache的默认缓存策略 -->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
maxElementsOnDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<persistence strategy="localTempSwap"/>
</defaultCache>
<!--
name:缓存名称。
maxElementsInMemory:缓存最大个数。
eternal:对象是否永久有效,一但设置了,timeout将不起作用。
timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
maxElementsOnDisk:硬盘最大缓存个数。
diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
clearOnFlush:内存数量最大时是否清除。
-->
<cache name="myToken"
maxElementsInMemory="100"
eternal="false"
timeToIdleSeconds="5400"
timeToLiveSeconds="5400"
maxElementsOnDisk="100"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<persistence strategy="localTempSwap"/>
</cache>
</ehcache>
3. 启动类加上注解
@EnableCaching
@SpringBootApplication
public class SpringbootEhcatchApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootEhcatchApplication.class, args);
}
}
4. 在类或者方法上加入缓存
@Cacheable(value = "myToken")
@Override
public Object findUserList(Integer pageNo, Integer pageSize) {
IPage<User> page = new Page<>(pageNo, pageSize);
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.orderByAsc("USER_ID");
IPage<User> userIPage = baseMapper.selectPage(page, wrapper);
return userIPage;
}
@Override // @Cacheable(value = USER_CACHE_NAME, key = "#id")@Cacheable(value = USER_CACHE_NAME, key = "'user' + #id")public User selectUserById(Integer id) {return userMapper.selectUserById(id);}@Override // @CacheEvict(value = USER_CACHE_NAME, key = "#id")@CacheEvict(value = USER_CACHE_NAME, key = "'user_' + #id")public void delete(Integer id) {userMapper.delete(id);}@Override // @CacheEvict(value = USER_CACHE_NAME, key = "#user.userId")@CacheEvict(value = USER_CACHE_NAME, key = "'user' + #user.userId") // @CachePut(value = USER_CACHE_NAME, key = "'user' + #user.userId") //测试发现只将结果清除,key未清除,导致查询继续使用缓存但结果为空????public void update(User user) {userMapper.update(user);}
三. Ehcache缓存清除
在实际的开发中,我们会对用户信息或者其他做缓存策略,但是当我们修改或者新增数据后,需要清除之前的缓存,重新查询放入缓存当中。我做了一个示例测试,在新增用户时我清除了缓存,如下:
@CacheEvict(value = "myToken", allEntries = true)
@Override
public Object addUser(String userName) {
User user = new User(null, userName);
int ret = baseMapper.insert(user);
return ret;
}
可以看到日志打印是这样的:说明了在新增用户时确实清除了之前的缓存,重新查询放入缓存,之后就直接从缓存中获取数据即可。
Ehcache集群模式
由于 EhCache 是进程中的缓存系统,一旦将应用部署在集群环境中,每一个节点维护各自的缓存数据,当某个节点对缓存数据进行更新,这些更新的数据无法在其它节点中共享,这不仅会降低节点运行的效率,而且会导致数据不同步的情况发生。例如某个网站采用 A、B 两个节点作为集群部署,当 A 节点的缓存更新后,而 B 节点缓存尚未更新就可能出现用户在浏览页面的时候,一会是更新后的数据,一会是尚未更新的数据,尽管我们也可以通过 Session Sticky 技术来将用户锁定在某个节点上,但对于一些交互性比较强或者是非 Web 方式的系统来说,Session Sticky 显然不太适合。
常用集群模式
EhCache从1.7版本开始,支持五种集群方案,分别是:
Terracotta、RMI、JMS、JGroups、EhCache Server
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。
集群模式缓存配置
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" />
<!-- 多台机器配置 rmiUrls=//192.168.8.32:4002/demoCache|//192.168.5.231:4003/demoCache -->
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,rmiUrls=//127.0.0.1:5000/userCache">
</cacheManagerPeerProviderFactory>
<!-- 配置 rmi 集群模式 -->
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=127.0.0.1,port=4000,socketTimeoutMillis=120000" />
<!-- 多播方式配置 搜索某个网段上的缓存 timeToLive 0是限制在同一个服务器 1是限制在同一个子网 32是限制在同一个网站 64是限制在同一个region
128是限制在同一个大洲 255是不限制 <cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=automatic, multicastGroupAddress=224.1.1.1, multicastGroupPort=40000,
timeToLive=32" /> -->
<!-- 默认缓存 -->
<defaultCache maxElementsInMemory="1000" eternal="true"
timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000"
diskPersistent="true" diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
<!-- demo缓存 -->
<cache name="userCache" maxElementsInMemory="1000" eternal="false"
timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000"
diskPersistent="false" diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" />
<!-- 用于在初始化缓存,以及自动设置 -->
<bootstrapCacheLoaderFactory
class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory" />
</cache>
</ehcache>
app2_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-5000" />
<!-- 多台机器配置 -->
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,rmiUrls=//127.0.0.1:4000/userCache">
</cacheManagerPeerProviderFactory>
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=127.0.0.1,port=5000,socketTimeoutMillis=120000" />
<!-- 多播方式配置 搜索某个网段上的缓存 timeToLive 0是限制在同一个服务器 1是限制在同一个子网 32是限制在同一个网站 64是限制在同一个region
128是限制在同一个大洲 255是不限制 <cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=automatic, multicastGroupAddress=224.1.1.1, multicastGroupPort=40000,
timeToLive=32" /> -->
<!-- 默认缓存 -->
<defaultCache maxElementsInMemory="1000" eternal="true"
timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000"
diskPersistent="true" diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
<!-- demo缓存 -->
<cache name="userCache" maxElementsInMemory="1000" eternal="false"
timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000"
diskPersistent="false" diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" />
<!-- 用于在初始化缓存,以及自动设置 -->
<bootstrapCacheLoaderFactory
class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory" />
</cache>
</ehcache>
其他同单节点
Ehcache的使用场景
使用纯java的ehcache作为本地缓存
Reids 作为远程分布式缓存
解决redis缓存压力过大,提高缓存速度,以及缓存性能。
Redis和Ehcache缓存的区别
如果是单个应用或者对缓存访问要求很高的应用,用ehcache。
如果是大型系统,存在缓存共享、分布式部署、缓存内容很大的,建议用redis。
实际工作中使用Ehcache
我们在项目中使用集中式缓存(Redis或者式Memcached等),通常都是检查缓存中是否存在
期望值的数据,如果存在直接返回,如果不存在就查询数据库让后在将数据库缓存,
这个时候如果缓存系统因为某写原因宕机,造成服务无法访问,那么大的量请求直接穿透到数据库,最数据库压力非常大。
这时候我们让ehcache作为二级缓存,当redis服务器宕机后,可以查询ehcache缓存。
这样能够有效的扛住服务器请求压力。
缓存应用(一)Ehcache使用介绍相关推荐
- java 使用ehcache,ehcache的介绍和使用,ehcache介绍使用
ehcache的介绍和使用,ehcache介绍使用 ehcache结合spring cache主要注解使用:@Cacheable,@CacheEvict,@CachePut 在语法和配置等方面的使用 ...
- Ehcache学习总结(1)--Ehcache入门介绍
Ehcache是现在最流行的纯Java开源缓存框架,配置简单.结构清晰.功能强大,最初知道它,是从hibernate的缓存开始的.网上中文的EhCache材料以简单介绍和配置方法居多,如果你有这方面的 ...
- Java缓存框架使用EhCache结合Spring AOP
Java缓存框架使用EhCache结合Spring AOP 一.Ehcache简介 EhCache是一个纯Java的进程内缓存框架,具有如下特点: 1. 快速简单,非常容易和应用集成. ...
- 【EhCache: 一款Java的进程内缓存框架】EhCache 是什么、代码实战、版本3的改进
文章目录 1 EhCache 是什么 2 EhCache 版本2 代码实战 Demo pom.xml TestEH.java ehcache.xml 3 EhCache 版本3 代码实战 Demo p ...
- 三大缓存框架(Ehcache+Memcache+Redis)基础
1.Ehcache(纯Java的进程内缓存框架,也叫二级缓存) Ehcache是一个开源的.设计于提高在数据从RDBMS中取出来的高花费.高延迟采取的一种缓存方案(在Java项目广泛的 使用).正因为 ...
- (转)使用 Spring缓存抽象 支持 EhCache 和 Redis 混合部署
背景:最近项目组在开发本地缓存,其中用到了redis和ehcache,但是在使用注解过程中发现两者会出现冲突,这里给出解决两者冲突的具体方案. spring-ehcache.xml配置: <?x ...
- Ehcache的介绍
1.Overview Ehcache从 Hibernate 发展而来,逐渐涵盖了Cahce界的全部功能,是目前发展势头最好的一个项目. 标准缓存 分布式缓存(基于RMI/JGroups/JMS) UR ...
- mybatis教程--查询缓存(一级缓存二级缓存和整合ehcache)
查询缓存 1 缓存的意义 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题. 2 mybat ...
- Springboot中的缓存Cache和CacheManager原理介绍
一.背景理解 什么是缓存,为什么要用缓存? 程序运行中,在内存保持一定时间不变的数据就是缓存.简单到写一个Map,里面放着一些key,value数据,就已经是个缓存了.所以缓存并不是什么高大上的技术, ...
- 三)mybatis 二级缓存,整合ehcache
mybatis-config.xml <setting name="cacheEnabled" value="true" /> PersonMapp ...
最新文章
- 在 Swift 中使用闭包实现懒加载
- 微服务架构 — Overview
- PHP 之旅 基础语法(二)
- C++string类型与C语言字符数组的转换 std::string.c_str()函数
- Red Hat Enterprise Linux Server release 5.6 安装 MongoDB 2.6.4
- python语言用什么关键字来声明一个类_python使用什么关键字定义类
- Java 平台有哪几个版本?
- Logistic回归模型(C++代码实现)
- 小程序UI库 iView Weapp
- 数学建模笔记(十):博弈模型
- 12个常见idea快捷键
- IntelliJ IDEA优化内存配置提高启动和运行速度
- 看美文,记单词(5)
- foxmail 登陆126邮箱
- 高校如何优雅的使用Ipv6--抱着道长的大腿
- 某某读书搜索__DATA__分析
- 使用PS切图时,调整标尺单位
- scala中的sealed
- 我的桌面布局(网络安全软件推荐)
- 关于PolarCode方案被5G标准采纳这件事