原创:实现ehcache动态创建cache,以及超期判断的具体逻辑
当前最常用的三个缓存组件:ehcache、redis、memcached
其中,ehcache与应用共同运行于JVM中,属于嵌入式组件,运行效率最高,因此常被用于实现一级缓存。
在更复杂的一些系统中,由于ehcache对集群/分布式的支持相对较弱,因此还会集成redis、memcached等,实现二级缓存。
ehcache的用法非常简单,只需要引入相关的Jar包,并创建一个配置文件,就可以在开发中使用了。
1、在Maven中添加ehcache的依赖:
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.4</version>
</dependency>
这个版本是发布到net.sf.ehcache的最后一个版本,也是2.x的最后一个版本。
在org.ehcache上有更新的3.x版本,功能更强大,写法差异也挺大。
由于2.x的核心功能已经非常稳定,已经完全满足系统需求,也更熟悉,因此我还是选择了这个2.10.4的版本。
2、创建配置文件:ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"
updateCheck="false"
dynamicConfig="false"> <diskStore path="java.io.tmpdir/myApp"/> <!--
默认缓存 属性说明:
maxElementsInMemory:内存中可保存的最大数量
eternal:缓存中对象是否为永久的。如果是,超时设置将被忽略
timeToIdleSeconds:对象最后一次访问之后的存活时间
timeToLiveSeconds:对象创建后的存活时间
memoryStoreEvictionPolicy:内存缓存的超期清理策略
maxElementsOnDisk:硬盘中可保存的最大数量
diskExpiryThreadIntervalSeconds:磁盘超期监控线程扫描时间间隔
overflowToDisk:内存不足时,是否启用磁盘缓存
-->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="1200"
maxElementsOnDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
overflowToDisk="true">
</defaultCache> </ehcache>
把这个配置文件保存到 src/main/resource 目录下即可。
3、实现动态创建Cache
在ehcache中,有两个最基本的对象:Cache 和 Element
其中,Cache相当于ehcache的分区,可以看成memcache中的Slab,上面配置文件中的 defaultCache 就是一个默认分区
每个Cache(分区)都类似一个Map<K, V>,可以通过Key来从Cache中返回缓存的Value。
每个KV键值对,在ehcache中,被称为Element(元素)。
要将任何一个对象添加到ehcache中,都需要事先指定分区
但在配置文件中创建分区很麻烦,通常只创建一个默认分区(必须存在),然后通过一个方法来动态创建分区:
/**
* 获取Cache,当Cache不存在时自动创建
*
* @param cacheName
* @return Cache
* @author netwild@qq.com
*/
public Cache getOrAddCache(String cacheName) {
Cache cache = cacheManager.getCache(cacheName);
if (cache == null) {
synchronized (locker) {
cache = cacheManager.getCache(cacheName);
if (cache == null) {
cacheManager.addCacheIfAbsent(cacheName);
cache = cacheManager.getCache(cacheName);
}
}
}
return cache;
}
这样的话,只需要像下面的用法,就可以很方便的把对象添加到缓存中:
String cacheName = "article";
String atricleId = "A00428";
Atricle article = AtricleService.findById(atricleId);
Element element = new Element(atricleId, article);
getOrAddCache(cacheName).put(element);
动态创建的Cache并不会出现在ehcache.xml配置文件中。
值得注意的是,上面动态创建Cache的方法中,并没有为新的Cache指定任何参数,那这些参数的默认值是多少呢?
其实,当创建Cache时,如果未传入参数默认值,将自动拷贝 defaultCache 的参数设置
就是说,配置文件中 defaultCache 的超期时间等属性将直接被应用到所有动态创建的Cache。
4、ehcache关于元素超期的判断逻辑
在ehcache.xml配置文件中,有两个关于元素超期的参数:
timeToLiveSeconds:对象创建后的存活时间
timeToIdleSeconds:对象最后一次访问之后的存活时间
这两个参数我忽略了将近一年的时间,一直在配置文件中对他们都设置了同样的参数值,比如:1200(20分钟)
刚才反复实验多次,终于将这两个参数搞清楚,才明白以前的做法是错误的
首先,这两个参数都可以单独设置而省略另一个,也可以分别设置成不同的值,当然也可以设置成相同的值,就像我以前做的那样
下面分别对这几种进行说明
1)单独设置 timeToLiveSeconds:
该对象的超期时间 = 初始创建时间 + timeToLiveSeconds
因为初始创建时间是固定的,因此不管这个对象在有效期内被命中了多少次,一旦满足超期条件,该对象将被移除。
2)单独设置 timeToIdleSeconds:
该对象的超时时间 = 最近访问时间 + timeToIdleSeconds
注意与上面的区别:不再根据创建时间,而是根据最近访问时间来确定超期时间
所以这是一种动态的超期模式,即使这个参数设置为1(秒),只要保证每秒内都能get一次,那么对象也将永远不会超期。
3)分别设置 timeToLiveSeconds 及 timeToIdleSeconds :
那么将分别计算以上两种模式的超期时间,会得出两个结果,再从两个结果里找到最小的一个做为超期时间,相当于“严苛模式”
但事实上,创建时间肯定会小于最近访问时间,那如果两者都设置同样的参数值,相当于 timeToIdleSeconds 永远也不会起到作用。
如果设置不同的参数值,根据具体的业务需求,可能会出现一些意料之中或者意料之外的情况。
综上所述,我的建议是,单独设置 timeToIdleSeconds 更恰当一些,对于在有效期内被频繁命中的缓存对象,可以自动“续期”。
5、最常用的操作之一:判断缓存中是否存在对象
在应用缓存的开发过程中,这是最常用的操作,目的是想要知道:目标对象是否已经被缓存过
通常下面的逻辑是:如果已被缓存过,那么直接拿出来使用;否则自力更生,完事之后再添加到缓存,下次就省事了
很多人是这样判断的:
return getOrAddCache(cacheName).get(key) != null;
但这种方式存在个问题:当缓存对象实际上存在,但值就是Null,这时就相当于忽略了缓存
所以我开始时是这样判断的:
return getOrAddCache(cacheName).isKeyInCache(key);
后来发现这种方式不会进行超期验证,就是说即使对象已经超期,只要当初被创建过,也会返回true
调整之后:
Cache cache = getOrAddCache(cacheName);
if(cache.isKeyInCache(key) && cache.getQuiet(key) != null){
return true;
}
return false;
这样就准确了!
原创:实现ehcache动态创建cache,以及超期判断的具体逻辑的更多相关文章
- Android实现多页左右滑动效果,支持子view动态创建和cache
要实现多页滑动效果,主要是需要处理onTouchEvent和onInterceptTouchEvent,要处理好touch事件的子控件和父控件的传递问题. 滚动控制可以利用android的Scroll ...
- [SAP ABAP开发技术总结]反射,动态创建内表、结构、变量
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- JavaScript DOM动态创建(声明)Object元素
http://www.cnblogs.com/GuominQiu/archive/2011/04/01/2002783.html 一文提及“等整个页面加载完毕后,根据用户所选的阅读机类型,再用Java ...
- 使用dxNavBar动态创建应用程序菜单
一.如何动态创建dxNavBar内容: function TMain.GetAcitonByCaption(const aCategory,aCaption: string): Integer; va ...
- Qt Quick 组件和动态创建的对象具体的解释
在<Qt Quick 事件处理之信号与槽>一文中介绍自己定义信号时,举了一个简单的样例.定义了一个颜色选择组件,当用户在组建内点击鼠标时,该组件会发出一个携带颜色值的信号,当时我使用 Co ...
- C#动态创建两个按钮,btn2复制btn1的Click事件,匿名委托
现在有一个按钮btn1,要动态创建出一个btn2,需要btn2点击时调用btn1的点击. 在delphi中这种操作很简单:btn2.onClick:=btn1.onClick,因为onClick就是个 ...
- ehcache-----在spring和hibernate下管理ehcache和query cache
1. 在Hibernate配置文件中设置: <!-- Hibernate SessionFactory --> <bean id="sessionFactory" ...
- C#动态创建Xml-LinQ方式
C#创建Xml-LinQ方式 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享 ...
- C# 动态创建SQL数据库(二) 在.net core web项目中生成二维码 后台Post/Get 请求接口 方式 WebForm 页面ajax 请求后台页面 方法 实现输入框小数多 自动进位展示,编辑时实际值不变 快速掌握Gif动态图实现代码 C#处理和对接HTTP接口请求
C# 动态创建SQL数据库(二) 使用Entity Framework 创建数据库与表 前面文章有说到使用SQL语句动态创建数据库与数据表,这次直接使用Entriy Framwork 的ORM对象关 ...
随机推荐
- wamp版本升级小问题记录
在升级wamp版本时遇到的一些小问题,特此记录 在安装完成之后,修改了Apache根目录,可以正常访问.但是发现 httpd-vhosts.conf追加配置的无法访问,逐步检查,有以下问题 1.Inc ...
- scrapy_cookie禁用_延迟下载_自定义爬虫setting
如何设置禁止cookie? 在setting中 添加字段: COOKIE_ENABLED = False # False关闭cookie,True ...
- CSS深入理解学习笔记之z-index
1.z-index基础 z-index含义:指定了元素及其子元素的"z顺序",而"z顺序"可以决定元素的覆盖顺序.z-index值越大越在上面. z-index ...
- C# MongoDB
一.搭建Mongodb 副本集 副本集中有三个角色: 主节点:所有副节点的数据均来自于主节点,并且只能对主节点进行读写操作.副节点:数据来自于主节点,可以进行读取操作,但是不能进行写操作.仲裁者:不含 ...
- 小白成长系列--HTTP协议(一)
序:小白成长系列是笔者使用最简单易懂的逻辑来解释常见的计算机相关知识,不仅理解,还让你记忆深刻\(^o^)/ 先理解什么是协议? 协议就是双方要做某件事情而制定的规则,而且双方必须要遵从协议所约定的内 ...
- 新版elasticsearch的插件安装
安装 yum localinstall elasticsearch-6.1.1.rpm -y mkdir -p /elk/{data,logs} && chown -R elastic ...
- 【转】linux shell 逻辑运算符、逻辑表达式
shell的逻辑运算符 涉及有以下几种类型,因此只要适当选择,可以解决很多复杂的判断. 一.逻辑运算符 逻辑卷标表示意思 1.关于档案与目录的侦测逻辑卷标! -f常用!侦测‘档案’是否存在 eg: ...
- GitHub For Beginners: Commit, Push And Go
In Part 1 of this two-part GitHub tutorial, we examined the main uses for GitHub and bega5n the proc ...
- WEB渗透测试之漏扫神器
AppScan 对现代 Web 应用程序和服务执行自动化的动态应用程序安全测试(DAST) 和交互式应用程序安全测试 (IAST).支持 Web 2.0. JavaScript 和 AJAX 框架的全 ...
- JavaScript 优雅简单的拼接字符串
前言 最近维护一个老系统,里面有大量js拼接字符串的代码,这里总计一下js拼接字符串 JS 原生字符串拼接 JavaScript里面的字符串可以直接用 + 来拼接 return "<a ...