- 浏览: 748209 次
- 性别:
- 来自: 苏州
文章分类
最新评论
-
hsl313:
源码还有得下载吗?
利用AMF数据封装与Flash 进行Socket通讯 -
zhang5476499:
已看,谢谢讲解。
Mock单元测试 -
Buydeful:
...
关于JSP或HTML的命名规范 -
lliiqiang:
单一登陆最好采用踢掉方法,如果忘记退出,可以从别的地方控制方式 ...
Jquery选择器大全 -
lliiqiang:
web代码由后台动态生成,这种动态方式多种多样,多提供几种标准 ...
Jquery选择器大全
http://www.iteye.com/topic/21727
Cache Insight
前言
首先,介绍一下我(作者)自己使用Cache的背景,以便读者更清楚地了解我下面要讲述哪些内容。
我主要是一个Cache实现者,而不是使用者。为了给一些ORM(比如JPA实现)提供Cache支持,我需要包装其它的Open Source Cache,并考察它们的特性。
我对这些Open Source Cache的一些工作原理,了解得比较多。具体配置和使用细节,了解的比较少。
本文主要讲述的也是Cache的特性和工作原理,而不是一个安装、配置、使用的入门手册。
本文简述Cache的一般特性,详述Cache的高级特性,比如,分布式Cache,关联对象的Cache,POJO Cache等。
阅读本文需要具备基本的Cluster知识,ORM知识,数据库事务知识。本文不解释这些基本概念。
-------------------------------------------------------
Cache Features
首先,我们来浏览一下常见的Cache。
这个链接给出了常用的Java Open Source Cache。
http://java-source.net/open-source/cache-solutions
memcached,JBoss Cache,SwarmCache,OSCache,JCS,EHCache等开源项目的出镜率和关注率比较高。
memcached和其他几个不同,后面会详述。
JBoss Cache的特点是,功能大而全,可算是Cache集大成者,几乎什么都支持。
其余的几个都很轻量。SwarmCache,OSCache,JCS支持Cluster。EHCache不支持Cluster。
下面列出Cache的基本特性。
1. 时间记录
数据进入Cache的时间。
2. timeout过期时间
Cache里面的数据多久过期
3. Eviction Policy 清除策略
Cache满了之后,根据什么策略,应该清除哪些数据。
比如,最不经常被访问的数据,最久没有访问到的数据。
4. 命中率
Cache的数据被选中的比率
5. 分级Cache
有些Cache有分级的概念。比如,几乎所有的Cache都支持Region分区的概念。可以指定某一类的数据存放在特定的Region里面。JBoss Cache可以支持更多的级别。
6. 分布式Cache
分布在不同计算机上的Cache
7. 锁,事务,数据同步
一些Cache提供了完善的锁,事务支持。
以上特性,大部分Cache都有相应的API支持。这些API很直观,也很简单,本文不打算展开讲述。
本文下面主要介绍,memcached和JBoss Cache这两个具有代表意义的Cache的高级特性,包括分布式Cache的支持。
-------------------------------------------------------
memcached
http://www.danga.com/memcached/
memcached是一个Client Server结构的远程Cache实现。
Server是用C写的,提供了多种语言的客户端API,包括Java, C#, Ruby, Python, PHP, Perl, C等多种语言。
memcached主要使用在Shared Nothing Architecture中。应用程序通过客户端API,从memcached server存取数据。
典型的应用,比如,用memcached作为数据库缓存。
也常有这样的用法,用memcached存放HTTP Session的数据。具体做法是包装Session Interface,截获setAttribute(), getAttribute()方法。
MemcachedSessionWrapper {
Object getAttribute( key ){
return memcachedClient.get (session.getId() + key);
}
void setAttribute( key, value ){
memcachedClient.setObject(session.getId() + key, value);
}
}
不同计算机上的应用程序通过一个IP地址来访问memcahced Server。
同一个key对应的数据,只存在于一台memcached server的一份内存中。
memcached server也可以部署在多台计算机上。Memcached通过key的hashcode来判断从哪台memcached server上存取数据数据。我们可以看到,同一个key对应的数据,还是只存在于一台memcached server的一份内存中。
所以,memcached不存在数据同步的问题。这个特性很关键,我们后面讲到Cluster Cache的时候,就会涉及到数据同步的问题。
memcached由于是远程Cache,要求放到Cache的Key和Value都是Serializable。
远程Cache,最令人担心的网络通信开销。据有经验的人说,memcached网络通信开销很小。
memcached的API设计也是远程通信友好的,提供了getMulti()等高粒度的调用方法,能够批量获取数据,从而减少网络通信次数。
-------------------------------------------------------
JBoss Cache
http://www.jboss.org/products/jbosscache
有一个商业Cluster Cache,叫做tangosol。
JBoss Cache是我唯一知道的能够和tangosol媲美的开源Cache。
Cluster Cache的数据同步,需要网络通信,这就要求放到Cache的数据是Serializable。
JBoss Cache提出了POJO Cache的概念,意思是数据不是Serializable,一样能够在Cluster中同步。
JBoss POJO Cache通过AOP机制,支持对象同步,支持对象属性的同步,支持关联对象的Cache,支持继承,集合,Query,并支持不同级别的事务,俨然一个小型内存数据库级别的数据存储系统。
下面进行解释。
最令人迷惑不解的是这个POJO的Cluster同步如何实现。
JBoss POJO Cache采用AOP来照管了POJO的通信和传播工作。天下没有免费的午餐,POJO不支持序列化,框架本身就要做这个工作——Marshal and Unmarshal,比如通过把Java对象翻译成XML,传播出去,对方收到XML,再翻译成Java对象。
上面说了,JBoss POJO Cache很像一个小型存储容器,JBoss POJO Cache的对象管理也非常类似Hibernate,JDO,JPA等ORM工具,同样有Detach和Attach的概念。
Attach就是put,把对象放入到Cache中。Detach就是remove,把对象从Cache中删除。为啥要多起个名?
原因是,put的时候,放进去的是个干干净净的POJO,出来的时候,就是Enhanced Object,里面夹杂了很多Interceptor代码,监听对象的方法。
你操作这个对象的时候,JBoss AOP框架就获得了相应的通知,能够做出相应的反应,比如数据同步等。
JBoss POJO Cache支持对集合类型的AOP。同样需要把集合Attach(Put)进Cache,然后get出来,然后对集合进行操作,就可以被JBoss AOP截获了。
JBoss POJO Cache的基础是JBoss Tree Cache。这个Tree Cache类似于一个XML DOM树形数据结构。
JBoss Cache采用Full Qualified Name作为Cache Key,类似于XPath。比如,a/b/c/d。
当你删除a/b的时候,a/b/c,a/b/c/d等所有属于a/b的Key和对应数据,都被删除。
JBoss Cache的findObjects方法能够找出一串对象。比如,findObjects根据a/b/c/d能够找出a,b,c,d等4个对象,放在一个Map中返回。
具体用法要参见API详细说明,因为JBoss POJO Cache提供了很多行为模式。
这种分级的Cache功能很有用,实现起来也不难。只是,我觉得,还是不够强大。既然支持了类似于XPath的Key,不如索性支持XPath的条件查询。比如,a[name=”n”]/b/c。当然,实现这种功能的代价非常大,需要遍历整个Cache Tree,正如XPath需要遍历整个DOM节点一样。
最后,JBoss Cache和tangosol一样,都支持了一个我认为如同鸡肋一般的功能,锁机制和事务支持。这个事务支持的意思是,Cache本身实现了类似于数据库的4种事务隔离级别。
在我看来,这种支持无疑是为了赚取眼球。Cache不当做Cache来用,搞些歪门邪道,大而不当。想当作数据库来用,那还不如把主要功夫花在上述提到的那种精确批量查询功能上。
-------------------------------------------------------
Cluster同步
Cluster之间的Cache同步有多种实现方法。比如,JMS,RMI,Client Server Socket等方法,用的最多的,支持最广的方法是JGroups开源项目实现的Multicast。配置Cluster Cache,通常就相当于配置JGroups,需要阅读JGroups配置文档。
Cache的操作通常有4个,get,put,remove,clear。
对于Cluster Cache来说,读操作(get)肯定是Local方法,只需要从本台计算机内存中获取数据。Remove/clear两个写操作,肯定是Remote方法,需要和Cluster其他计算机进行同步。Put这个写方法,可以是Local,也可以是Remote的。
Remote Put方法的场景是这样,一台计算机把数据放到Cache里面,这个数据就会被传播到Cluster其他计算机上。这个做法的好处是Cluster各台计算机的Cache数据可以及时得到补充,坏处是传播的数据量比较大,这个代价比较大
Local Put方法的场景是这样,一台计算机把数据放到Cache里面,这个数据不会被传播到Cluster其他计算机上。这个做法的好处是不需要传播数据,坏处是Cluster各台计算机的Cache数据不能及时得到补充,这个不是很明显的问题,从Cache中得不到数据,从数据库获取数据是很正常的现象。
Local Put比起Remote Put的优势很明显,所以,通常的Cluster Cache都采用Local Put的策略。各Cache一般都提供了Local Put的配置选项,如果你没有看到这个支持,那么请换一个Cache。:D
-------------------------------------------------------
Center vs Cluster
Memcached可以看作是Center Cache。
Center Cache和Cluster Cache的特性比较如下:
Center Cache没有同步问题,所以,remove/clear的时候,比较有优势,不需要把通知发送到好几个计算机上。
但是,Center Cache的所有操作,get/put/remove/clear都是Remote操作。而Cluster Cache的get/put都是Local操作,所以,Cluster Cache在get/put操作上具有优势。
Local get/put在关联对象的组装和分拆方面,优势比较明显。
关联对象的分拆是这个意思。
比如,有一个Topic对象,下面有几个Post对象,每个Post对象都有一个User对象。
Topic对象存放到Cache中的时候,下面的关联对象都要拆开来,分成各自的Entity Region来存放。
Topic Region -> Topic ID -> Topic Object
Post Region -> Post ID -> Post Object
User Region -> User ID -> User Object
这个时候,put的动作可能发生多次。Remote Put的开销就比较大。
Get的过程类似,也需要get多次,才能拼装成一个完整的Topic对象。
-------------------------------------------------------
过期数据
Cache可以用在任何地方,比如,页面缓存。但Cache的最常用场景是用在ORM中,比如,Hibernate,JDO,JPA中。
ORM Cache的使用方法有个原则——不要把没有Commit的修改数据放入到缓存中。这是为了防止Read Dirty。
数据库事务分为两种,一种是读事务,不修改数据,一种是写事务,修改数据。
写事务的操作流程如下:
db.commt();
cache.remove(key); // 这一步操作,清除了Cache数据,也记录了一个时间removeTime。
读事务的操作流程如下:
readTime = current time;
data = cache.get(key);
if(data is null){
data = db.load(key);
cache.put(key, data, readTime); // 这里要readTime传进去
}
这里需要注意的是put的时候,需要readTime这个参数。
这个readTime要和上一次的removeTime进行比较。
如果readTime > removeTime,这个put才能成功,数据才能够进入缓存。
这是为了保证不把过期数据放入到Cache中,及时反映数据库的变化。
另外,需要注意的是,cache.remove(key); 这个事件需要传播到Cluster其他计算机,通知它们清理缓存。
为什么需要这个通知?
一定要注意,这不是为了避免并发修改冲突。并发修改冲突的避免需要引入乐观锁版本控制机制。
有可能存在这样的误解,认为有了乐观锁版本控制机制,就不需要Cache.remove通知了。这是不对的。
Cache.remove通知的主要目的是,保证缓存能够及时清理过期数据,反映数据的变化,保证大部分时间内,应用程序显示给用户的不是过期数据。
另外,db.commt(); cache.remove(key); 这两步调用之间,有很小的可能发生另外的事务。这段极小的时间内,可能无法保证Read Committed,可能出现很短期的过期数据。
为什么说很短期,因为紧接着的Cache.remove就会清理过期数据。
如果偏执到这种程度,这么短期的几乎不可能发生的小概率事件,都不能容忍,那么可以,db.commt()之前,给Cache加一个悲观锁,不让别的事务,把数据Put进入Cache,就可以防止这个小概率、微影响的事件。
JBoss Cache和Tangosol就提供了这类鸡肋一般的悲观锁机制。典型的开发资源配置不当,有用的需要的不做,没用的功能使劲做。
ORM Query Cache
ORM Cache一般分为两种。一种是ID Cache(ORM文档中称为二级Cache),用来存放Entity ID对应的Entity对象;一种是Query Cache,用来存放一条查询语句对应的查询结果集。
ID Cache非常直观,如同上述讲述的,一般是一个Entity Class对应一个Region,Entity存放到对应的Region里面。
Query Cache比较复杂,而且潜在作用很大,值得仔细讲解。
现有的ORM对Query Cache的支持并不是很理想。
比如,Hibernate把整个结果集直接放在Query Cache中。这样,有任何风吹草动,发生了任何数据库的写操作,Query Cache都需要清空。
有一种比较好的做法,把ID List存放在Query Cache中,每次获取的时候,先获取ID List,然后根据ID List获取Entity List。Query Cache根据Query涉及到的Table Name来进行清理,一旦发生对这些Table Name的修改操作,就可以根据不同情况,清理Query Cache。
比如,select t2.* from t1, t2 where t1.id = t2.foreign_id and t1.name = ‘a’
那么insert into t1, delete from t1, insert into t2, delete from t2都会清除这条Query Cache。
同样的 update t1 set name = … 这样的语句也会清除这条Query Cache。
Hibernate为什么不这么做,因为Query Cache的情况比较复杂。也许选择的结果集并不是只有一个Entity类型,也许只是几个字段。
这个地方,如果细分,还是有很多功夫可以做的。而且也很值得花功夫做,因为Query Cache对于性能的提高,有很大作用。
-------------------------------------------------------
ORM Query Cache
Cache可以用在任何地方,比如,页面缓存。但Cache的最常用场景是用在ORM中,比如,Hibernate,JDO,JPA中。
ORM Cache一般分为两种。一种是ID Cache(ORM文档中称为二级Cache),用来存放Entity ID对应的Entity对象;一种是Query Cache,用来存放一条查询语句对应的查询结果集。
ID Cache非常直观,如同上述讲述的,一般是一个Entity Class对应一个Region,Entity存放到对应的Region里面。
Query Cache比较复杂,而且潜在作用很大,值得仔细讲解。
现有的ORM对Query Cache的支持并不是很理想。
比如,Hibernate把整个结果集直接放在Query Cache中。这样,有任何风吹草动,发生了任何数据库的写操作,Query Cache都需要清空。
有一种比较好的做法,把ID List存放在Query Cache中,每次获取的时候,先获取ID List,然后根据ID List获取Entity List。Query Cache根据Query涉及到的Table Name来进行清理,一旦发生对这些Table Name的修改操作,就可以根据不同情况,清理Query Cache。
比如,select t2.* from t1, t2 where t1.id = t2.foreign_id and t1.name = ‘a’
那么insert into t1, delete from t1, insert into t2, delete from t2都会清除这条Query Cache。
同样的 update t1 set name = … 这样的语句也会清除这条Query Cache。
Hibernate为什么不这么做,因为Query Cache的情况比较复杂。也许选择的结果集并不是只有一个Entity类型,也许只是几个字段。
这个地方,如果细分,还是有很多功夫可以做的。而且也很值得花功夫做,因为Query Cache对于性能的提高,有很大作用。
-----------------------------------------------------------
Query Key
Query Cache的性能需要考虑几个方面。比如,Query Key。Query Key一般由2个部分组成:Query String部分,SQL, HQL, EQL, or OQL;参数部分。
寻找Query Key的对应数据的时候,Query Key的比较有两个步骤,先hash,然后equals。所以,Query Key的hashcode和equals两个方法很重要。尤其是equals方法。
equals方法需要比较很长的Query String。如果没有命中,Query String不相等,那么开销很小,因为通常来说,不相等的String长度都不同,或者前面的字符串都不相同。开销最大的是命中的时候,Query String相等,那么需要把String从头比到尾。
我们可以采取一些方法来提高String的比较速度。比如,大部分的情况属于静态查询,我们可以采用Singleton String。相同reference的String之间的比较速度很快。对于ORM来说,最好直接使用最外面的HQL, EQL, OQL作为Query Key,而不是采用生成的SQL结果。因为生成的SQL结果每次都是一个新String,具有不同的reference,Cache命中的时候,需要比较整个字符串。
动态拼装的Query String的性能提高比较难办。因为最终的结果,都是一个新String。我采用的一种方式是,动态拼装的结果是一个String[]。两个String[]如果相等,那么里面的元素String的reference都是相等的,这是由JVM对一个Class内部的String常量进行优化的结果。
比如,
String[] a = {
“select * from t where”
“a = 1”
“and b = 2”
};
String[] b = {
“select * from t where”
“a = 1”
“and b = 2”
};
那么a和b的比较只需要3次String reference的比较。
Cache Insight
前言
首先,介绍一下我(作者)自己使用Cache的背景,以便读者更清楚地了解我下面要讲述哪些内容。
我主要是一个Cache实现者,而不是使用者。为了给一些ORM(比如JPA实现)提供Cache支持,我需要包装其它的Open Source Cache,并考察它们的特性。
我对这些Open Source Cache的一些工作原理,了解得比较多。具体配置和使用细节,了解的比较少。
本文主要讲述的也是Cache的特性和工作原理,而不是一个安装、配置、使用的入门手册。
本文简述Cache的一般特性,详述Cache的高级特性,比如,分布式Cache,关联对象的Cache,POJO Cache等。
阅读本文需要具备基本的Cluster知识,ORM知识,数据库事务知识。本文不解释这些基本概念。
-------------------------------------------------------
Cache Features
首先,我们来浏览一下常见的Cache。
这个链接给出了常用的Java Open Source Cache。
http://java-source.net/open-source/cache-solutions
memcached,JBoss Cache,SwarmCache,OSCache,JCS,EHCache等开源项目的出镜率和关注率比较高。
memcached和其他几个不同,后面会详述。
JBoss Cache的特点是,功能大而全,可算是Cache集大成者,几乎什么都支持。
其余的几个都很轻量。SwarmCache,OSCache,JCS支持Cluster。EHCache不支持Cluster。
下面列出Cache的基本特性。
1. 时间记录
数据进入Cache的时间。
2. timeout过期时间
Cache里面的数据多久过期
3. Eviction Policy 清除策略
Cache满了之后,根据什么策略,应该清除哪些数据。
比如,最不经常被访问的数据,最久没有访问到的数据。
4. 命中率
Cache的数据被选中的比率
5. 分级Cache
有些Cache有分级的概念。比如,几乎所有的Cache都支持Region分区的概念。可以指定某一类的数据存放在特定的Region里面。JBoss Cache可以支持更多的级别。
6. 分布式Cache
分布在不同计算机上的Cache
7. 锁,事务,数据同步
一些Cache提供了完善的锁,事务支持。
以上特性,大部分Cache都有相应的API支持。这些API很直观,也很简单,本文不打算展开讲述。
本文下面主要介绍,memcached和JBoss Cache这两个具有代表意义的Cache的高级特性,包括分布式Cache的支持。
-------------------------------------------------------
memcached
http://www.danga.com/memcached/
memcached是一个Client Server结构的远程Cache实现。
Server是用C写的,提供了多种语言的客户端API,包括Java, C#, Ruby, Python, PHP, Perl, C等多种语言。
memcached主要使用在Shared Nothing Architecture中。应用程序通过客户端API,从memcached server存取数据。
典型的应用,比如,用memcached作为数据库缓存。
也常有这样的用法,用memcached存放HTTP Session的数据。具体做法是包装Session Interface,截获setAttribute(), getAttribute()方法。
MemcachedSessionWrapper {
Object getAttribute( key ){
return memcachedClient.get (session.getId() + key);
}
void setAttribute( key, value ){
memcachedClient.setObject(session.getId() + key, value);
}
}
不同计算机上的应用程序通过一个IP地址来访问memcahced Server。
同一个key对应的数据,只存在于一台memcached server的一份内存中。
memcached server也可以部署在多台计算机上。Memcached通过key的hashcode来判断从哪台memcached server上存取数据数据。我们可以看到,同一个key对应的数据,还是只存在于一台memcached server的一份内存中。
所以,memcached不存在数据同步的问题。这个特性很关键,我们后面讲到Cluster Cache的时候,就会涉及到数据同步的问题。
memcached由于是远程Cache,要求放到Cache的Key和Value都是Serializable。
远程Cache,最令人担心的网络通信开销。据有经验的人说,memcached网络通信开销很小。
memcached的API设计也是远程通信友好的,提供了getMulti()等高粒度的调用方法,能够批量获取数据,从而减少网络通信次数。
-------------------------------------------------------
JBoss Cache
http://www.jboss.org/products/jbosscache
有一个商业Cluster Cache,叫做tangosol。
JBoss Cache是我唯一知道的能够和tangosol媲美的开源Cache。
Cluster Cache的数据同步,需要网络通信,这就要求放到Cache的数据是Serializable。
JBoss Cache提出了POJO Cache的概念,意思是数据不是Serializable,一样能够在Cluster中同步。
JBoss POJO Cache通过AOP机制,支持对象同步,支持对象属性的同步,支持关联对象的Cache,支持继承,集合,Query,并支持不同级别的事务,俨然一个小型内存数据库级别的数据存储系统。
下面进行解释。
最令人迷惑不解的是这个POJO的Cluster同步如何实现。
JBoss POJO Cache采用AOP来照管了POJO的通信和传播工作。天下没有免费的午餐,POJO不支持序列化,框架本身就要做这个工作——Marshal and Unmarshal,比如通过把Java对象翻译成XML,传播出去,对方收到XML,再翻译成Java对象。
上面说了,JBoss POJO Cache很像一个小型存储容器,JBoss POJO Cache的对象管理也非常类似Hibernate,JDO,JPA等ORM工具,同样有Detach和Attach的概念。
Attach就是put,把对象放入到Cache中。Detach就是remove,把对象从Cache中删除。为啥要多起个名?
原因是,put的时候,放进去的是个干干净净的POJO,出来的时候,就是Enhanced Object,里面夹杂了很多Interceptor代码,监听对象的方法。
你操作这个对象的时候,JBoss AOP框架就获得了相应的通知,能够做出相应的反应,比如数据同步等。
JBoss POJO Cache支持对集合类型的AOP。同样需要把集合Attach(Put)进Cache,然后get出来,然后对集合进行操作,就可以被JBoss AOP截获了。
JBoss POJO Cache的基础是JBoss Tree Cache。这个Tree Cache类似于一个XML DOM树形数据结构。
JBoss Cache采用Full Qualified Name作为Cache Key,类似于XPath。比如,a/b/c/d。
当你删除a/b的时候,a/b/c,a/b/c/d等所有属于a/b的Key和对应数据,都被删除。
JBoss Cache的findObjects方法能够找出一串对象。比如,findObjects根据a/b/c/d能够找出a,b,c,d等4个对象,放在一个Map中返回。
具体用法要参见API详细说明,因为JBoss POJO Cache提供了很多行为模式。
这种分级的Cache功能很有用,实现起来也不难。只是,我觉得,还是不够强大。既然支持了类似于XPath的Key,不如索性支持XPath的条件查询。比如,a[name=”n”]/b/c。当然,实现这种功能的代价非常大,需要遍历整个Cache Tree,正如XPath需要遍历整个DOM节点一样。
最后,JBoss Cache和tangosol一样,都支持了一个我认为如同鸡肋一般的功能,锁机制和事务支持。这个事务支持的意思是,Cache本身实现了类似于数据库的4种事务隔离级别。
在我看来,这种支持无疑是为了赚取眼球。Cache不当做Cache来用,搞些歪门邪道,大而不当。想当作数据库来用,那还不如把主要功夫花在上述提到的那种精确批量查询功能上。
-------------------------------------------------------
Cluster同步
Cluster之间的Cache同步有多种实现方法。比如,JMS,RMI,Client Server Socket等方法,用的最多的,支持最广的方法是JGroups开源项目实现的Multicast。配置Cluster Cache,通常就相当于配置JGroups,需要阅读JGroups配置文档。
Cache的操作通常有4个,get,put,remove,clear。
对于Cluster Cache来说,读操作(get)肯定是Local方法,只需要从本台计算机内存中获取数据。Remove/clear两个写操作,肯定是Remote方法,需要和Cluster其他计算机进行同步。Put这个写方法,可以是Local,也可以是Remote的。
Remote Put方法的场景是这样,一台计算机把数据放到Cache里面,这个数据就会被传播到Cluster其他计算机上。这个做法的好处是Cluster各台计算机的Cache数据可以及时得到补充,坏处是传播的数据量比较大,这个代价比较大
Local Put方法的场景是这样,一台计算机把数据放到Cache里面,这个数据不会被传播到Cluster其他计算机上。这个做法的好处是不需要传播数据,坏处是Cluster各台计算机的Cache数据不能及时得到补充,这个不是很明显的问题,从Cache中得不到数据,从数据库获取数据是很正常的现象。
Local Put比起Remote Put的优势很明显,所以,通常的Cluster Cache都采用Local Put的策略。各Cache一般都提供了Local Put的配置选项,如果你没有看到这个支持,那么请换一个Cache。:D
-------------------------------------------------------
Center vs Cluster
Memcached可以看作是Center Cache。
Center Cache和Cluster Cache的特性比较如下:
Center Cache没有同步问题,所以,remove/clear的时候,比较有优势,不需要把通知发送到好几个计算机上。
但是,Center Cache的所有操作,get/put/remove/clear都是Remote操作。而Cluster Cache的get/put都是Local操作,所以,Cluster Cache在get/put操作上具有优势。
Local get/put在关联对象的组装和分拆方面,优势比较明显。
关联对象的分拆是这个意思。
比如,有一个Topic对象,下面有几个Post对象,每个Post对象都有一个User对象。
Topic对象存放到Cache中的时候,下面的关联对象都要拆开来,分成各自的Entity Region来存放。
Topic Region -> Topic ID -> Topic Object
Post Region -> Post ID -> Post Object
User Region -> User ID -> User Object
这个时候,put的动作可能发生多次。Remote Put的开销就比较大。
Get的过程类似,也需要get多次,才能拼装成一个完整的Topic对象。
-------------------------------------------------------
过期数据
Cache可以用在任何地方,比如,页面缓存。但Cache的最常用场景是用在ORM中,比如,Hibernate,JDO,JPA中。
ORM Cache的使用方法有个原则——不要把没有Commit的修改数据放入到缓存中。这是为了防止Read Dirty。
数据库事务分为两种,一种是读事务,不修改数据,一种是写事务,修改数据。
写事务的操作流程如下:
db.commt();
cache.remove(key); // 这一步操作,清除了Cache数据,也记录了一个时间removeTime。
读事务的操作流程如下:
readTime = current time;
data = cache.get(key);
if(data is null){
data = db.load(key);
cache.put(key, data, readTime); // 这里要readTime传进去
}
这里需要注意的是put的时候,需要readTime这个参数。
这个readTime要和上一次的removeTime进行比较。
如果readTime > removeTime,这个put才能成功,数据才能够进入缓存。
这是为了保证不把过期数据放入到Cache中,及时反映数据库的变化。
另外,需要注意的是,cache.remove(key); 这个事件需要传播到Cluster其他计算机,通知它们清理缓存。
为什么需要这个通知?
一定要注意,这不是为了避免并发修改冲突。并发修改冲突的避免需要引入乐观锁版本控制机制。
有可能存在这样的误解,认为有了乐观锁版本控制机制,就不需要Cache.remove通知了。这是不对的。
Cache.remove通知的主要目的是,保证缓存能够及时清理过期数据,反映数据的变化,保证大部分时间内,应用程序显示给用户的不是过期数据。
另外,db.commt(); cache.remove(key); 这两步调用之间,有很小的可能发生另外的事务。这段极小的时间内,可能无法保证Read Committed,可能出现很短期的过期数据。
为什么说很短期,因为紧接着的Cache.remove就会清理过期数据。
如果偏执到这种程度,这么短期的几乎不可能发生的小概率事件,都不能容忍,那么可以,db.commt()之前,给Cache加一个悲观锁,不让别的事务,把数据Put进入Cache,就可以防止这个小概率、微影响的事件。
JBoss Cache和Tangosol就提供了这类鸡肋一般的悲观锁机制。典型的开发资源配置不当,有用的需要的不做,没用的功能使劲做。
ORM Query Cache
ORM Cache一般分为两种。一种是ID Cache(ORM文档中称为二级Cache),用来存放Entity ID对应的Entity对象;一种是Query Cache,用来存放一条查询语句对应的查询结果集。
ID Cache非常直观,如同上述讲述的,一般是一个Entity Class对应一个Region,Entity存放到对应的Region里面。
Query Cache比较复杂,而且潜在作用很大,值得仔细讲解。
现有的ORM对Query Cache的支持并不是很理想。
比如,Hibernate把整个结果集直接放在Query Cache中。这样,有任何风吹草动,发生了任何数据库的写操作,Query Cache都需要清空。
有一种比较好的做法,把ID List存放在Query Cache中,每次获取的时候,先获取ID List,然后根据ID List获取Entity List。Query Cache根据Query涉及到的Table Name来进行清理,一旦发生对这些Table Name的修改操作,就可以根据不同情况,清理Query Cache。
比如,select t2.* from t1, t2 where t1.id = t2.foreign_id and t1.name = ‘a’
那么insert into t1, delete from t1, insert into t2, delete from t2都会清除这条Query Cache。
同样的 update t1 set name = … 这样的语句也会清除这条Query Cache。
Hibernate为什么不这么做,因为Query Cache的情况比较复杂。也许选择的结果集并不是只有一个Entity类型,也许只是几个字段。
这个地方,如果细分,还是有很多功夫可以做的。而且也很值得花功夫做,因为Query Cache对于性能的提高,有很大作用。
-------------------------------------------------------
ORM Query Cache
Cache可以用在任何地方,比如,页面缓存。但Cache的最常用场景是用在ORM中,比如,Hibernate,JDO,JPA中。
ORM Cache一般分为两种。一种是ID Cache(ORM文档中称为二级Cache),用来存放Entity ID对应的Entity对象;一种是Query Cache,用来存放一条查询语句对应的查询结果集。
ID Cache非常直观,如同上述讲述的,一般是一个Entity Class对应一个Region,Entity存放到对应的Region里面。
Query Cache比较复杂,而且潜在作用很大,值得仔细讲解。
现有的ORM对Query Cache的支持并不是很理想。
比如,Hibernate把整个结果集直接放在Query Cache中。这样,有任何风吹草动,发生了任何数据库的写操作,Query Cache都需要清空。
有一种比较好的做法,把ID List存放在Query Cache中,每次获取的时候,先获取ID List,然后根据ID List获取Entity List。Query Cache根据Query涉及到的Table Name来进行清理,一旦发生对这些Table Name的修改操作,就可以根据不同情况,清理Query Cache。
比如,select t2.* from t1, t2 where t1.id = t2.foreign_id and t1.name = ‘a’
那么insert into t1, delete from t1, insert into t2, delete from t2都会清除这条Query Cache。
同样的 update t1 set name = … 这样的语句也会清除这条Query Cache。
Hibernate为什么不这么做,因为Query Cache的情况比较复杂。也许选择的结果集并不是只有一个Entity类型,也许只是几个字段。
这个地方,如果细分,还是有很多功夫可以做的。而且也很值得花功夫做,因为Query Cache对于性能的提高,有很大作用。
-----------------------------------------------------------
Query Key
Query Cache的性能需要考虑几个方面。比如,Query Key。Query Key一般由2个部分组成:Query String部分,SQL, HQL, EQL, or OQL;参数部分。
寻找Query Key的对应数据的时候,Query Key的比较有两个步骤,先hash,然后equals。所以,Query Key的hashcode和equals两个方法很重要。尤其是equals方法。
equals方法需要比较很长的Query String。如果没有命中,Query String不相等,那么开销很小,因为通常来说,不相等的String长度都不同,或者前面的字符串都不相同。开销最大的是命中的时候,Query String相等,那么需要把String从头比到尾。
我们可以采取一些方法来提高String的比较速度。比如,大部分的情况属于静态查询,我们可以采用Singleton String。相同reference的String之间的比较速度很快。对于ORM来说,最好直接使用最外面的HQL, EQL, OQL作为Query Key,而不是采用生成的SQL结果。因为生成的SQL结果每次都是一个新String,具有不同的reference,Cache命中的时候,需要比较整个字符串。
动态拼装的Query String的性能提高比较难办。因为最终的结果,都是一个新String。我采用的一种方式是,动态拼装的结果是一个String[]。两个String[]如果相等,那么里面的元素String的reference都是相等的,这是由JVM对一个Class内部的String常量进行优化的结果。
比如,
String[] a = {
“select * from t where”
“a = 1”
“and b = 2”
};
String[] b = {
“select * from t where”
“a = 1”
“and b = 2”
};
那么a和b的比较只需要3次String reference的比较。
发表评论
-
转:Node.js 究竟是什么?
2011-09-05 09:19 1002简介 如果您听说过 ... -
Asynchronous innerHTML
2009-06-02 10:39 1089A recent question on Stack Over ... -
Fastest way to build an HTML string
2009-06-02 10:28 1152You have a massive array of ite ... -
JS字符串加不同浏览器比较
2009-05-06 09:03 1856function StringBuffer() { ... -
kestrel项目
2009-05-02 01:58 1563kestrel项目,用于MQ,twitter实现 scala语 ... -
Tomcat6安装版本参数修改
2009-04-14 13:41 1516tomcat6w.exe //ES//Tomcat6 -Xr ... -
jvm之JSTAT
2008-12-23 16:02 2985http://java.sun.com/javase/6/do ... -
jvm之JPS
2008-12-23 10:45 1652PARAMETERS options ... -
jvm之JSTATD
2008-12-23 10:26 2612PARAMETERS options ... -
JVM监控工具介绍
2008-12-15 10:43 2994http://hqman.iteye.com/blog/167 ... -
java6性能
2008-12-10 10:55 1697J2SE 6(代号:Mustang野马 ... -
ApacheBench测试工具使用指南
2008-12-01 15:46 2267服务器负载太大而影响程序效率也是很常见的,Apache服务器自 ... -
关于fastcgi的一些摘录
2008-12-01 14:17 1495原讨论帖:http://www.iteye.com/topic ... -
基于等待的性能调优
2008-11-20 12:40 1092性能调优曾经是“艺术性”多于“科学性”,但是通过结合抽象分析和 ... -
Web 图片服务器
2008-08-25 14:11 2968http://www.yatan.com/group/topi ... -
图片加速
2008-08-18 11:43 1906不要GZIP图片,设置Cache 图片已经是压缩保存了的,GZ ... -
Ajax performance analysis
2008-07-22 11:28 1236http://www.ibm.com/developerwor ... -
HashMap和List的线程安全
2008-03-24 08:54 4620Map m =Collections.synchronized ... -
HTTP协议:304
2008-01-24 17:59 5932var r = new XMLHttpRequest(); ... -
【摘录】缓存
2008-01-21 10:37 1445robbin: 1、对象缓存 Java ...
相关推荐
fc-cache -fv ``` 2. 添加字体到source insight 然后,我们需要将字体文件夹复制到source insight的字体目录下: ``` cp –R winFonts/*.* /home/wine-1.6.2/fonts ``` 3. 设置字体 现在,我们可以设置source ...
CMake Error: The current CMakeCache.txt directory C:/DC105_Dupli.SearchResults/build/CMakeCache.txt is different than the directory c:/D/DC105_xxxx/trunk/build where CMakeCache.txt was created....
- 硬件环境初始化:包括进入svc模式、关闭watchdog、屏蔽所有IRQ掩码、设置时钟频率、清除I/D cache、禁用MMU和CACHE、配置memorycontrol。 - 代码重定位:如果代码不在链接指定的地址上,则需要将u-boot拷贝到RAM...
“A virtual arms cache at your fingertips. HackNotes Linux and Unix Security Portable Reference is a valuable reference for busy administrators and consultants who value the condensed and practical ...
- **Sequence Syntax**:`CREATE SEQUENCE [IF NOT EXISTS] schema.seq [START WITH ] [MINVALUE ] [MAXVALUE ] [INCREMENT BY ] [CACHE <constant> | NOCACHE] [CYCLE | NOCYCLE];` - **访问Sequence**:使用`...
Virtual Image Exception功能允许将标准虚拟机映像中的文件添加到白名单,避免不必要的扫描,而资源分级和Shared Insight Cache功能则进一步提高了效率,避免了重复扫描。 总的来说,Symantec Endpoint Protection...
9. **Shared Insight Cache**:在整个主机上共享扫描结果,虚拟机首次遇到文件时扫描并填充缓存,后续只需查询缓存,避免重复扫描。 10. **脱机映像扫描工具**:Symantec Offline Image Scanner可以扫描VMware脱机...
Specific topics covered include process management, scheduling, time management and timers, the system call interface, memory addressing, memory management, the page cache, the VFS, kernel ...
Take advantage of the various data providers to access authentication and authorization, sessions, cache, and database Leverage asynchronous processing for decoupling components to ease scaling ...
8. "(boston university2002)Cache-and-relay streaming media delivery.pdf":波士顿大学在2002年的研究可能涉及缓存和中继在P2P流媒体交付中的作用,以优化网络效率。 9. "VoD_Streaming_Synchronization_...
这些控制器用于管理和优化硬盘存储性能,其中FBWC(Flash Backed Write Cache)是用于提高数据完整性和性能的技术。 9. 电源供应方面,文档列出了不同服务器型号支持的功率,如“350W”、“460W”、“300W”等,这...
FBWC(Flash-Based Write Cache)模块的LED指示灯则可以显示缓存模块的状态,如是否正常工作等。 #### 结论 通过对HP ProLiant DL388p Gen8服务器LED指示灯的详细介绍,我们可以看出,这些指示灯不仅提供了服务器...
6. **Shared Insight Cache**:这是一个缓存服务,确保相同的文件只需扫描一次,减少网络和CPU资源的消耗,同时支持物理和虚拟环境。 7. **虚拟客户端标记**:能够识别虚拟机并实施特定的策略,有助于管理和优化...
3. **Shared Insight Cache server**:共享洞察缓存服务器提升了在虚拟化环境中的扫描效率,通过共享威胁数据库,减少了网络带宽的消耗。 4. **Virtual Client Tagging**:虚拟客户端标识功能帮助区分和管理虚拟...
在软件定义存储方面,FusionStorage利用分布式Cache、DHT算法和分区分配算法,实现高性能分布式存储,有效利用SSD缓存,提高读写速度。而在软件定义网络领域,华为通过Agile Controller和OpenStack Neutron实现了跨...
HP ProLiant Gen9服务器的核心优势在于其自动化和管理功能,如HP ProActive Insight架构,它简化了服务器的维护和升级。例如,HP Smart Socket提供了易于访问和升级的处理器接口,而HP SmartDrives则加强了硬盘监控...
相较于Source Insight等其他同类工具,Kscope在速度及功能方面有着显著的优势。本文旨在详细介绍如何在Ubuntu 9.10系统上安装Kscope 1.6.2版本,包括必要的依赖安装、编译配置以及常见问题解决方法。 #### 二、准备...
- **MMU/Cache支持**:支持在MMU Enable和Cache Enable模式下进行调试,这对于开发高性能应用来说是非常重要的。 #### 七、注意事项 - 在使用过程中,需要注意不要在DaemonU图标显示红绿灯闪烁状态时关闭硬件电源...