项目缓存方案总结

一、 hibernate的二级缓存
如果开启了二级缓存,hibernate在执行任何一次查询的之后,都会把得到的结果集放到缓存中,缓存结构可以看作是一个hash table,key是数据库记录的id,value是id对应的pojo对象。当用户根据id查询对象的时候(load、iterator办法),会首先在缓存中查找,如果没有找到再发起数据库查询。但是如果使用hql发起查询(find, query办法)则不会利用二级缓存,而是直接从数据库获得数据,但是它会把得到的数据放到二级缓存备用。也就是说,基于hql的查询,对二级缓存是只写不读的。

针对二级缓存的工作原理,采用iterator取代list来提高二级缓存命中率的想法是不可行的。Iterator的工作方法是根据检索条件从数据库中选取所有目标数据的id,然后用这些id一个一个的到二级缓存里面做检索,如果找到就直接加载,找不到就向数据库做查询。因此假如iterator检索100条数据的话,最好情况是100%全部命中,最坏情况是0%命中,执行101条sql把所有数据选出来。而list虽然不利用缓存,但是它只会发起1 条sql取得所有数据。在合理利用分页查询的情况下,list整体效率高于iterator。

二级缓存的失效机制由hibernate控制,当某条数据被修改之后,hibernate会根据它的id去做缓存失效操作。基于此机制,如果数据表不是被hibernate独占(比如同时使用JDBC或者ado等),那么二级缓存无法得到有效控制。

由于hibernate的缓存接口很灵活,cacheprovider可以方便的切换,因此支持cluster环境不是大问题,通过使用swarmcache、jboss cache等支持分布式的缓存方案,可以实现。但是问题在于:
1、 分布式缓存本身成本偏高(比如使用同步复制模式的jboss cache)
2、 分布式环境通常对事务控制有较高规定,而目前的开源缓存方案对事务缓存(transaction cache)支持得不够好。当jta事务发生会滚,缓存的最后更新结果很难预料。这一点会带来很大的部署成本,甚至得不偿失。

结论:不应把hibernate二级缓存作为优化的主要手段,一般情况下建议不要使用。

缘故如下:
1、 项目的DAO类大部分是从1.0升级过来,由于1.0采用的是 hibernate 2.1,所以在批量删除数据的时候采用了native sql的方法。虽然2.0已经完全升级到 hibernate3.2,支持hibernate原生的批量删改,但是由于hibernate批量操作的性能不如sql,而且为了兼容1.0的dao 类,所以不少地方保留了sql操作。哪些数据表是单纯被hibernate独占无法统计,而且随着将来业务的成长可能会有很大变数。因此不宜采用二级缓存。
2、 针对系统业务来说,基于id检索的二级缓存命中率极为有限,hql被大部份采用,二级缓存对性能的提升很有限。
3、 hibernate 3.0 在做批量修改、批量更新的时候,是不会同步更新二级缓存的,该问题在hibernate 3.2中是否仍然存在尚不确定。

  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6