1、OSCache是什么?
OSCache标记库由OpenSymphony设计,它是一种开创性的缓存方案,它提供了在现有JSP页面之内实现内存缓存的功能。OSCache是个一个被广泛采用的高性能的J2EE缓存框架,OSCache还能应用于任何Java应用程序的普通的缓存解决方案。
2、OSCache的特点
(1) 缓存任何对象:你可以不受限制的缓存部分jsp页面或HTTP请求,任何java对象都可以缓存。
(2) 拥有全面的API:OSCache API允许你通过编程的方式来控制所有的OSCache特性。
(3) 永久缓存:缓存能被配置写入硬盘,因此允许在应用服务器的多次生命周期间缓存创建开销昂贵的数据。
(4) 支持集群:集群缓存数据能被单个的进行参数配置,不需要修改代码。
(5) 缓存过期:你可以有最大限度的控制缓存对象的过期,包括可插入式的刷新策略(如果默认性能不能满足需要时)。
3、OSCache缓存的三种模式
(1)缓存于内存中
(2)缓存于硬盘中
(3)一种较灵活的方式,先缓存于内存中,如果满了则转至硬盘
4、OSCache的安装与配置
OSCache是当前运用最广的缓存方案,JBoss,Hibernate,Spring等都对其有支持
下面简单介绍一下OSCache的配置和使用过程。
1.安装过程
从http://www.opensymphony.com/oscache/download.html下载合适的OSCache版本
解压压缩文件得到文件夹oscache-2.4.1-full
从解压缩目录取得oscache.jar 文件放到/WEB-INF/lib 或相应类库目录中,jar文件名可能含有版本号和该版本的发布日期信息等,如oscache-2.4.1.jar
将lib下的commons-logging.jar和jgroups-all.jar都放入到/WEB-INF/lib中
拷贝OSCache标签库文件oscache.tld到src目录或者/WEB-INF/classes目录。
从src或etc目录取得oscache.properties 文件,放入src根目录或发布环境的/WEB-INF/classes 目录
如你需要建立磁盘缓存,须修改oscache.properties 中的cache.path信息 (去掉前面的#注释)。
内容如下:
Cache.manory=false;
cache.persistence.class=com.opensymphony.oscache.plugins.diskpersistence.HashPersistenceListener;
win类路径类似为c:\\app\\cache
unix类路径类似为/opt/myapp/cache
现在你的应用目录类似如下:
$WEB_APPLICATION\WEB-INF\lib\oscache.jar
$WEB_APPLICATION\WEB-INF\lib\commons-logging.jar
$WEB_APPLICATION\WEB-INF\lib\jgroups-all.jar
$WEB_APPLICATION\WEB-INF\classes\oscache.properties
$WEB_APPLICATION\WEB-INF\classes\oscache.tld
将下列代码加入web.xml文件中即可使用OSCache提供的标签了
<jsp-config>
<taglib>
<taglib-uri>oscache</taglib-uri>
<taglib-location>/WEB-INF/classes/oscache.tld</taglib-location>
</taglib>
</jsp-config>
2.oscache.properties 文件配置向导(源文件已经写好了只要将语句前面的#号去掉即可)
cache.memory值为true 或 false ,默认为在内存中作缓存,如设置为false,即将缓存的数据存到cache.path配置好的路径下
cache.capacity:缓存元素个数
cache.persistence.class 持久化缓存类,如此类打开,则必须设置cache.path信息
cache.cluster 相关
为集群设置信息。
如
cache.cluster.multicast.ip为广播IP地址
cache.cluster.properties为集群属性
5.OSCache的基本用法
1.OSCache标签的使用
注意:要使用标签必须在web.xml中配置好之后再在页面中引入,在页面开始加入<%@ taglib uri="oscache"prefix="cache" %>句即可
以下两个页面是使用OSCache标签的例子:
index1.jsp 内容如下
<%@page import="java.util.*" %>
<%@taglib uri="oscache" prefix="cache" %>
<html>
<body>
<!―未使用到标签-->
没有缓存的日期: <%= new Date() %>
<!--自动刷新但是没有给标记符key赋值-->
<cache:cache time="30">
每30秒刷新缓存一次的日期:<%= new Date() %>
</cache:cache>
<!--手动刷新,给标记符key赋值了-->
<cache:cache key="testcache">
手动刷新缓存的日期: <%= new Date() %> <p>
</cache:cache>
<ahref="index2.jsp">手动刷新</a>
</body>
</html>
index2.jsp 执行手动刷新页面如下:
<%@taglib uri="oscache" prefix="cache" %>
<html>
<body>
缓存已刷新...<p>
<!―根据key定位到index1.jsp页面的testcache,范围为application,使用的是flush标签用来清空缓存-->
<cache:flush key="testcache" scope="application"/>
<a href="index1.jsp">返回</a>
</body>
</html>
你也可以通过下面语句定义Cache的有效范围,如不定义scope,scope默认为Applcation
<cache:cache time="30"scope="session">
内容...
</cache:cache>
6. 缓存过滤器 CacheFilter
如果是对页面进行缓存则需要在web.xml中定义缓存过滤器,定义特定资源的缓存。
<filter>
<filter-name>CacheFilter</filter-name>
<filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class>
<init-param>
<param-name>time</param-name>
<param-value>60</param-value>
</init-param>
<init-param>
<param-name>scope</param-name>
<param-value>session</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CacheFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
上面定义将缓存所有.jsp页面,缓存刷新时间为60秒,缓存作用域为Session
注意:如果要加入其它的属性的话只要添加一个<init-param>标签对,在其中添加相应的属性,用法跟在jsp页面使用标签是一致的
注意,CacheFilter只捕获Http头为200的页面请求,即只对无错误请求作缓存,而不对其他请求(如500,404,400)作缓存处理
7、主要的标签以及标签属性
Cache标签――缓存代码段主要使用到的标签:
属性说明:
key
标识缓存内容的关键词。在指定的作用范围内必须是唯一的。默认的key是被访问页面的URI和后面的请求字符串。可以在同一个页面中使用很多cache 标签而不指定他的key属性,这种情况下系统使用该页面的URI和后面的请求字符串,另外再自动给这些key增加一个索引值来区分这些缓存内容。但是不推 荐采用这样的方式。
scope
缓存发生作用的范围,可以是application或者session。默认为application。
time
缓存内容的时间段,单位是秒,默认是3600秒,也就是一个小时,如果设定一个负值,那么这部分被缓存的内容将永远不过期。
duration
指定缓存内容失效的时间,是相对time的另一个选择,可以使用简单日期格式或者符合USO-8601的日期格式。如:duration='PT5M' duration='5s'等。
注意:time与duration的区别是time的单位是秒所以设置的时候是只要输入一个阿拉伯数字,而duration的话可以使用简单日期格式或者符合USO-8601的日期格式。如:duration='PT5M' duration='5s'等
cron
指定缓存内容失效表达式。
通过Cron表达式我们可以很灵活的设置缓存的失效时间,Cron表达式包括5个字段分别为Minute,Hour, DOM(Day Of Month), Month,DOW(Day Of Week)。他们顺序地对应了5个位置。当某个位置上的值为*时,表示该位置上的任意时间。另外还提供了指定时间的操作符号"-",",","/",他们 分别表示一段时间范围,具体的时间,以及递增的时间段。下面是几个例子说明一下Cron表达式的基本应用:
(1) "10/20 * * * *" :因是第一个位置,并且是一个递增的表达式,所以表达式指定的是每个小时的第10分钟,第30分钟,第50分钟缓存内容失效。
(2) "* 8-18/4 * * *" :指定每天早上8点到晚上6点之间,每4个小时缓存内容失效。 等同于"*8,12,16 * * *"。
(3) "* * * * 1-5":表示每个星期一到星期五内容失效。
refresh
false 或者true。如果refresh属性设置为true,不管其他的属性是否符合条件,这部分被缓存的内容都将被更新,这给编程者一种选择,决定什么时候必须刷新。
mode
如果不希望被缓存的内容增加到给用户的响应中,可以设置mode属性为"silent"。此时被缓存的部分不在页面上显示,而其它任意的mode属性值都会将缓存的部分显示到页面上。
groups
指定当前cache标签所属的组,可使用“,”分割组名。这样就可以对缓存项进行分组了。如果缓存项依赖于应用的其它部分或其它数据,分组就有了用武之地――当这种依赖改变时(刷新相关的组),这个组的所有缓存项都将过期。
language
使用ISO-639定义的语言码来发布不同的缓存内容(under an otherwise identical key)。要在一个多语言网站上同一段JSP代码不同用户的参数提供不同的语言时,这个属性会很有用。
refreshpolicyclass
指定自定义的刷新策略类的全限定类名。这个类继承自
com.opensymphony.oscache.web.WebEntryRefreshPolicy
refreshpolicyparam
指定任意需要传给refreshpolicyclass的参数。如果没有指定refreshpolicyclass,则这个值不起作用。
usecached标签
<usecached />:必须嵌套在<cache>标签中。
属性说明:
use
告诉所在的<cache>标签是否使用已经缓存的内容(缺省为true,使用缓存的内容)。可以使用这个标签来控制缓存。比如使用<frush>标签刷新某个key的缓存,但可以在必要的地方即使这样的强制刷新也仍然使用缓存内容而不刷新。
flush标签
这个标签用于在运行时刷新缓存。只有运行flush标签后再次访问相关缓存项时才执行刷新。
属性说明:
scope[all]
指定要刷新的范围。可选的值是"application","session" 和 nul。null(到底是null量还是all呀)值指定刷新所有的缓存(是指使用cache标签的缓存)。
key
当指定了scope和key值时,刷新唯一的缓存项。当这个缓存项下次被访问时将被刷新。只指定一个key值而没有指定scope不起作用。
group
指定一个组时将刷新所有这个组中的缓存项。只指定一个group值而没有指定scope不起作用。
pattern
任意包含pattern属性指定的值的缓存项都将被刷新。只指定一个pattern值而没有指定scope不起作用。 (注意:OSCache项目组已经不赞成使用pattern这个属性赖刷新缓存,二是鼓励使用具有更好的灵活性和性能的group属性来代替)
language
使用ISO-639定义的语言码来发布不同的缓存内容(under an otherwise identical key)。要在一个多语言网站上同一段JSP代码不同用户的参数提供不同的语言时,这个属性会很有用。
addgroup标签
<addgroup />:必须嵌套在<cache>标签中。
属性说明:
group
定义cache标签的group名称
示例代码如下:
<oscache:cache key="test1">
<oscache:addgroupgroup="group1" />
... some jsp content ...
<oscache:addgroupgroup="group2" />
... some more jsp content ...
</oscache:cache>
#一、内存缓存或硬盘、数据库缓存
cache.memory=false
#二、缓存的最大数量。默认是不限制,cache不会移走任何缓存内容。负数被视不限制。
cache.capacity=100
#三、运算规则。为了使用规则,cache的size必须是指定的。
#如果cache的size不指定的话, 将不会限制缓存对象的大小。如果指定了cache的size,但不指定algorithm,那它会默认使用:com.opensymphony.oscache.base.algorithm.LRUCache
#有下面三种规则:
#*com.opensymphony.oscache.base.algorithm.LRUCache:
#last in first out(最后插入的最先调用)。默认选项。
#*com.opensymphony.oscache.base.algorithm.FIFOCache:
#first int first out(最先插入的最先调用)。
#*com.opensymphony.oscache.base.algorithm.UnlimitedCache :
#cache中的内容将永远不会被丢弃。
#如果cache.capacity不指定值的话,它将被设为默认选项。
cache.algorithm=com.opensymphony.oscache.base.algorithm.LRUCache
#四、是否同步。true 或者 false。一般设为true,避免读取脏数据。
cache.blocking=true
#五、指定硬盘缓存是否要作限制。默认值为false。false的状况下,disk cache capacity 和cache.capacity的值相同。
cache.unlimited.disk=false
#六、指定类是被持久化缓存的类。class必须实现PersistenceListener接口。
#作为硬盘持久,可以实现com.opensymphony.oscache.plugins.diskpersistence.HashDiskPersistenceListener接口。
#它把class的toString()输出的hash值作为文件的名称。如果你要想文件名易读些(自己设定),DiskPersistenceListener 的父类也能使用,但其可能有非法字符或者过长的名字。
#注意:HashDiskPersistenceListener 和 DiskPersistenceListener 需要设定硬盘路径:cache.path
#cache.persistence.class=
#七、指定硬盘缓存的路径。目录如果不存在将被建立。同时注意oscache应该要有权限写文件系统。
#例: cache.path=c:\\myapp\\cache cache.path=/opt/myapp/cache
cache.path=e:\\index\\cache
#八、指定是否只有在内存不足的情况下才使用硬盘缓存。
#默认值false。但推荐是true如果内存cache被允许的话。这个属性彻底的改变了cache的行为,使得persisted cache和memory是完全不同。
cache.persistence.overflow.only=false
#九、class名列表(用逗号隔开)。每个class必须实现以下接口中的一个 或者几个
#CacheEntryEventListener:接收cache add/update/flush and remove事件
#CacheMapAccessEventListener :接收cache访问事件。这个可以让你跟踪cache怎么工作。
#默认是不配置任何class的。当然你可以使用一下的class:
#*com.opensymphony.oscache.plugins.clustersupport.BroadcastingCacheEventListener : 分布式的监听器。可以广播到局域网内的其他cache实例。
#* com.opensymphony.oscache.extra.CacheEntryEventListenerImpl :一个简单的监听器。在cache的生命周期中记录所有entry的事件。
#* com.opensymphony.oscache.extra.CacheMapAccessEventListenerImpl : 记录count of cache map events(cache hits,misses and state hits).
#cache.event.listeners
#十、在application 和 session的作用域时 用于标识cache 对象的, 用于ServletCacheAdministrator;此属性不是指定为"__oscache_cache"格式时为默认值, 如果代码中需要用到默认值时可以通使用com.opensymphony.oscache.base.Const.DEFAULT_CACHE_KEY 来取得;
cache.key=__oscache_cache
#十一、当配置多个服务器时,想通过服备器名称自动生成cache key时,可将此属性设为true. 默认值为false;
cache.use.host.domain.in.key=true
#十二、 在以上基础选项之上可以加入一些额外的属性到此文件中.例: JavaGroupsBroadcastingListener 便是额外的
#Additional Properties
#十三、用于缓存集群. 默认为231.12.21.132
#cache.cluster.multicast.ip
#十四、 指集群中的额外配置项. 以下是默认设置:(此属性的相关说将在集群文档中说明)
#UDP(mcast_addr=231.12.21.132;mcast_port=45566;ip_ttl=32;\
#mcast_send_buf_size=150000;mcast_recv_buf_size=80000):\
#PING(timeout=2000;num_initial_members=3):\
#MERGE2(min_interval=5000;max_interval=10000):\
#FD_SOCK:VERIFY_SUSPECT(timeout=1500):\
#pbcast.NAKACK(gc_lag=50;retransmit_timeout=300,600,1200,2400,4800;max_xmit_size=8192):\
#UNICAST(timeout=300,600,1200,2400):\
#pbcast.STABLE(desired_avg_gossip=20000):\
#FRAG(frag_size=8096;down_thread=false;up_thread=false):\
#pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;print_local_addr=true)
#cache.cluster.properties
# CACHE IN MEMORY
#
# If you want to disable memory caching, just uncomment this line.
#
# cache.memory=false
# CACHE KEY
#
# This is the key that will be used to store the cache in the application
# and session scope.
#
# If you want to set the cache key to anything other than the default
# uncomment this line and change the cache.key
#
# cache.key=__oscache_cache
# USE HOST DOMAIN NAME IN KEY
#
# Servers for multiple host domains may wish to add host name info to
# the generation of the key. If this is true, then uncomment the
# following line.
#
# cache.use.host.domain.in.key=true
# CACHE LISTENERS
#
# These hook OSCache events and perform various actions such as logging
# cache hits and misses, or broadcasting to other cache instances across a cluster.
# See the documentation for further information.
#
# cache.event.listeners=com.opensymphony.oscache.plugins.clustersupport.JMSBroadcastingListener, \
# com.opensymphony.oscache.extra.CacheEntryEventListenerImpl, \
# com.opensymphony.oscache.extra.CacheMapAccessEventListenerImpl, \
# com.opensymphony.oscache.extra.ScopeEventListenerImpl, \
# com.opensymphony.oscache.extra.StatisticListenerImpl
# CACHE PERSISTENCE CLASS
#
# Specify the class to use for persistence. If you use the supplied DiskPersistenceListener,
# don't forget to supply the cache.path property to specify the location of the cache
# directory.
#
# If a persistence class is not specified, OSCache will use memory caching only.
#
# cache.persistence.class=com.opensymphony.oscache.plugins.diskpersistence.DiskPersistenceListener
# cache.persistence.class=com.opensymphony.oscache.plugins.diskpersistence.HashDiskPersistenceListener
# CACHE OVERFLOW PERSISTENCE
# Use persistent cache in overflow or not. The default value is false, which means
# the persistent cache will be used at all times for every entry. true is the recommended setting.
#
# cache.persistence.overflow.only=true
# CACHE DIRECTORY
#
# This is the directory on disk where caches will be stored by the DiskPersistenceListener.
# it will be created if it doesn't already exist. Remember that OSCache must have
# write permission to this directory.
#
# Note: for Windows machines, this needs \ to be escaped
# ie Windows:
# cache.path=c:\\myapp\\cache
# or *ix:
# cache.path=/opt/myapp/cache
#
# cache.path=c:\\app\\cache
# CACHE ALGORITHM
#
# Default cache algorithm to use. Note that in order to use an algorithm
# the cache size must also be specified. If the cache size is not specified,
# the cache algorithm will be Unlimited cache.
#
# cache.algorithm=com.opensymphony.oscache.base.algorithm.LRUCache
# cache.algorithm=com.opensymphony.oscache.base.algorithm.FIFOCache
# cache.algorithm=com.opensymphony.oscache.base.algorithm.UnlimitedCache
# THREAD BLOCKING BEHAVIOR
#
# When a request is made for a stale cache entry, it is possible that another thread is already
# in the process of rebuilding that entry. This setting specifies how OSCache handles the
# subsequent 'non-building' threads. The default behaviour (cache.blocking=false) is to serve
# the old content to subsequent threads until the cache entry has been updated. This provides
# the best performance (at the cost of serving slightly stale data). When blocking is enabled,
# threads will instead block until the new cache entry is ready to be served. Once the new entry
# is put in the cache the blocked threads will be restarted and given the new entry.
# Note that even if blocking is disabled, when there is no stale data available to be served
# threads will block until the data is added to the cache by the thread that is responsible
# for building the data.
#
# cache.blocking=false
# CACHE SIZE
#
# Default cache size in number of items. If a size is specified but not
# an algorithm, the cache algorithm used will be LRUCache.
#
#cache.capacity=1000
# CACHE UNLIMITED DISK
# Use unlimited disk cache or not. The default value is false, which means
# the disk cache will be limited in size to the value specified by cache.capacity.
#
# cache.unlimited.disk=false
# JMS CLUSTER PROPERTIES
#
# Configuration properties for JMS clustering. See the clustering documentation
# for more information on these settings.
#
#cache.cluster.jms.topic.factory=java:comp/env/jms/TopicConnectionFactory
#cache.cluster.jms.topic.name=java:comp/env/jms/OSCacheTopic
#cache.cluster.jms.node.name=node1
# JAVAGROUPS CLUSTER PROPERTIES
#
# Configuration properites for the JavaGroups clustering. Only one of these
# should be specified. Default values (as shown below) will be used if niether
# property is set. See the clustering documentation and the JavaGroups project
# (www.javagroups.com) for more information on these settings.
#
#cache.cluster.properties=UDP(mcast_addr=231.12.21.132;mcast_port=45566;ip_ttl=32;\
#mcast_send_buf_size=150000;mcast_recv_buf_size=80000):\
#PING(timeout=2000;num_initial_members=3):\
#MERGE2(min_interval=5000;max_interval=10000):\
#FD_SOCK:VERIFY_SUSPECT(timeout=1500):\
#pbcast.NAKACK(gc_lag=50;retransmit_timeout=300,600,1200,2400,4800;max_xmit_size=8192):\
#UNICAST(timeout=300,600,1200,2400):\
#pbcast.STABLE(desired_avg_gossip=20000):\
#FRAG(frag_size=8096;down_thread=false;up_thread=false):\
#pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;print_local_addr=true)
#cache.cluster.multicast.ip=231.12.21.132
同一个应用可以实例化多个oscache的admin,使用不同的配置策略,如不同的配置文件。例如:
Java代码
Public class ChatRecordCache {
private static GeneralCacheAdministrator admin;
private static String OSCACHE_DISK = "oscache_disk.properties";
static {
Properties prop = new Properties();
try {
prop.load(new FileInputStream(OSCACHE_DISK));
} catch (FileNotFoundException e) {
// e.printStackTrace();
} catch (IOException e) {
// e.printStackTrace();
}
admin = new GeneralCacheAdministrator(prop);
}
}
对应的配置文件为oscache_disk.properties:
Java代码
cache.persistence.class=com.opensymphony.oscache.plugins.diskpersistence.DiskPersistenceListener
cache.path=/opt/myapp/cache
cache.algorithm=com.opensymphony.oscache.base.algorithm.FIFOCache
cache.capacity=1000
cache.unlimited.disk=true
Java代码
public class ChatUserCache {
private static GeneralCacheAdministrator admin = new GeneralCacheAdministrator();
}
此处采用默认的配置文件oscache.properties.
注意:如果多个cache实例产生的硬盘缓存路径和缓存名称完全相同,将会无法区分,此时要注意设置不同的key值区分。
关于NeedsRefreshException,引用官方文档中的一段例子如下:
Java代码
// ---------------------------------------------------------------
// Typical use with fail over
// 采取补救措施的典型方案
// ---------------------------------------------------------------
String myKey = "myKey";
String myValue;
int myRefreshPeriod = 1000;
try {
// Get from the cache
myValue = (String) admin.getFromCache(myKey, myRefreshPeriod);
} catch (NeedsRefreshException nre) {
//This exception is thrown when retrieving an item from cache and it //is expired. Note that for fault tolerance purposes, it is possible //to retrieve the current cached object from the exception.
try {
// Get the value (probably by calling an EJB)
myValue = "This is the content retrieved.";
// Store in the cache
admin.putInCache(myKey, myValue);//有解锁的作用
} catch (Exception ex) {//获取myValue过程发生异常,无法执行到putInCache方法
// We have the current content if we want fail-over.
//采取补救措施,获取可能的值(适用于数据过期的情况)
myValue = (String) nre.getCacheContent();
// It is essential that cancelUpdate is called if the
// cached content is not rebuilt
admin.cancelUpdate(myKey);//解锁
}
}
这段代码是使用oscache的经典代码,细说如下。myValue = (String) admin.getFromCache(myKey, myRefreshPeriod);从对象缓存map中取出myKey对应的对象,两种情况可能发生: 一:如果myKey对应的对象存在(先前putInCache)并且没有过期(isStale()方法)那么getFromCache方法会正常返回。二:如果对应的对象不存在或者过期,分为两种情况:1)请求的线程第一个探测到对象不存在或者过期,那么这个时候oscache会抛出一个NeedRefreshException, 提示需要对数据进行一下刷新,怎么刷新,putInCache或者cancelUpdate即可。2)如果请求的线程并非第一个探测到对象不存在,两种情况:A.之前探测到的线程没有进行刷新处理,直接阻塞。B. 之前探测到的线程进行了刷新处理,抛出NeedRefreshException。3)如果请求的线程并非第一个探测到对象过期,两种情况:A.之前探测到的线程没有进行刷新处理,直接阻塞。B. 之前探测到的线程进行了刷新处理,又分两种情况:I.如果oscache.properties中对blocking设置为false(默认cache.blocking=false), 抛出NeedRefreshException,此处采取补救措施nre.getCacheContent(),会取出现有(很可能过期)内容。 II. 如果cache.blocking=true那么该线程会在此阻塞,直到putInCache在另一个线程中被调用或者是cancelUpdate被调用。参考以下说明:
cache.blocking
When a request is made for a stale cache entry, it is possible that another thread is already in the process of rebuilding that entry. This setting specifies how OSCache handles the subsequent 'non-building' threads. The default behaviour (cache.blocking=false) is to serve the old content to subsequent threads until the cache entry has been updated. This provides the best performance (at the cost of serving slightly stale data). When blocking is enabled, threads will instead block until the new cache entry is ready to be served. Once the new entry is put in the cache the blocked threads will be restarted and given the new entry.
Note that even if blocking is disabled, when there is no stale data available to be served threads will block until the data is added to the cache by the thread that is responsible for building the data.
补充:oscache对一个cacheEntry是否是Stale(或者说expire)的判断原则:
1.Cache.flushEntry()
2.Cache.flushAll()
3.CacheEntry.setGroups(groups); Cache.flushGroup(group)
4.createTime + refreshPeriod< now
5.cronExpiry< now
6.CacheEntry自带的EntryRefreshPolish的needRefresh方法返回true
上面的6条中的任何一条如果为true, 那么CacheEntry就是stale的,need refresh!
官方文档中的另一段例子如下:
Java代码
// ---------------------------------------------------------------
// Typical use without fail over
//不采取补救措施的典型方案
// ---------------------------------------------------------------
String myKey = "myKey";
String myValue;
int myRefreshPeriod = 1000;
try {
// Get from the cache
myValue = (String) admin.getFromCache(myKey, myRefreshPeriod);
} catch (NeedsRefreshException nre) {
try {
// Get the value (probably by calling an EJB)
myValue = "This is the content retrieved.";
// Store in the cache
admin.putInCache(myKey, myValue);
updated = true;
} finally {
if (!updated) {
// It is essential that cancelUpdate is called if the
// cached content could not be rebuilt
admin.cancelUpdate(myKey);
}
}
}
// ---------------------------------------------------------------