Cache

下面列出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可以用在任何地方,比如,页面缓存。但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对于性能的提高,有很大作用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值