设为首页 加入收藏

TOP

Hibernate性能优化之EHCache缓存
2015-07-16 12:55:15 来源: 作者: 【 】 浏览:3
Tags:Hibernate 性能 优化 EHCache 缓存

像Hibernate这种ORM框架,相较于JDBC操作,需要有更复杂的机制来实现映射、对象状态管理等,因此在性能和效率上有一定的损耗。


在保证避免映射产生低效的SQL操作外,缓存是提升Hibernate的关键之一。


加入缓存可以避免数据库调用带来的连接创建与销毁、数据打包拆包、SQL执行、网络传输,良好的缓存机制和合理的缓存模式能带来性能的极大提升,EHCache就提供了这种良好的缓存机制。


Hibernate的缓存机制


--------------------------------------------------------------------------------


缓存的级别一般分为三种,每一种缓存的范围更大:


事务级缓存:Hibernate中称为一级缓存,在一个Session中共享缓存对象;


应用级缓存:Hibernate中称为二级缓存,在一个SessionFactory中共享缓存对象,SessionFactory在整个应用范围内重用;


分布式缓存:部署为单独的实例,如Redis、Memcache等。


Hibernate的按以下方式进行缓存:


当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;


查不到,如果配置了二级缓存,那么从二级缓存中查;


如果都查不到,再查询数据库,把结果按照ID放入到缓存删除、更新、增加数据的时候,同时更新缓存。


Hibernate默认不启用二级缓存,EHCache是Hibernate中的二级缓存插件,使用Hibernate的系统可以直接使用EHCache缓存。


为什么要直接使用EHCache


--------------------------------------------------------------------------------


回头来看那句话:良好的缓存机制和合理的缓存模式能带来性能的极大提升。


Hibernate的缓存模式是什么?


根据ID来缓存对象,也就是Session的get、load操作时。


这种缓存模式的弊端有两点:


1、应用场景太单一,系统中大量的列表式查询缓存起不到作用;


2、一些系统中通过ThreadLocal在线程中重用Session,每个线程可能需要大量处理不用的业务逻辑,缓存命中率很低;如果不重用Session,一般的场景缓存命中率更低。


既然EHCache已经提供了良好的缓存机制,结合自己系统的业务来优化缓存模式才是最佳的。


如何使用EHCache


--------------------------------------------------------------------------------


EHCache是Hibernate中的二级缓存插件,使用Hibernate的系统可以直接使用EHCache缓存,不需要再添加其他jar包。


新建EHCache配置文件,具体的配置含义可以查手册:


? xsi:noNamespaceSchemaLocation="ehcache.xsd">?
? ?
? ? ? maxElementsInMemory="10000"?
? ? maxElementsOnDisk="0"?
? ? eternal="true"?
? ? overflowToDisk="true"?
? ? diskPersistent="false"?
? ? timeToIdleSeconds="0"?
? ? timeToLiveSeconds="0"?
? ? diskSpoolBufferSizeMB="50"?
? ? diskExpiryThreadIntervalSeconds="120"?
? ? memoryStoreEvictionPolicy="LFU"?
? ? />?
? ? ? maxElementsInMemory="100"?
? ? maxElementsOnDisk="0"?
? ? eternal="false"?
? ? overflowToDisk="false"?
? ? diskPersistent="false"?
? ? timeToIdleSeconds="119"?
? ? timeToLiveSeconds="119"?
? ? diskSpoolBufferSizeMB="50"?
? ? diskExpiryThreadIntervalSeconds="120"?
? ? memoryStoreEvictionPolicy="FIFO"?
? ? />?
?


EHCache的一个优点是线程安全的,适合多线程的使用场景,能简化开发人员的使用。


因此我写了一个单例模式,避免每次在方法里写getCache,这个类也涵盖了EHCache的基本使用:


public class EHCacheFactory {
? ?
? ? private final CacheManager manager;
? ? private final Cache cache;
? ?
? ? private EHCacheFactory() {
? ? ? ? manager = CacheManager.create(getClass().getResource("/ehcache.xml"));
? ? ? ? cache = manager.getCache("restCache");
? ? }
? ?
? ? public Element getCache(String strKey) {
? ? ? ? return EHCacheFactory.getInstance().getCache().get(strKey);
? ? }
? ?
? ? public void setCache(String strKey, String strVal) {
? ? ? ? EHCacheFactory.getInstance().getCache().put(new Element(strKey, strVal));
? ? }
? ?
? ? public Cache getCache() {
? ? ? ? return cache;
? ? }
? ?
? ? private static class SingletonHolder {


? ? ? ? private final static EHCacheFactory INSTANCE = new EHCacheFactory();
? ? }


? ? public static EHCacheFactory getInstance() {
? ? ? ? return SingletonHolder.INSTANCE;
? ? }
}


我的系统是JAVA REST,在需要缓冲的REST接口中加入了EHCache缓存,通过URL参数作为缓存键值,REST接口返回的json数据作为缓存值,这种缓存模式非常适合REST。


使用ab进行了简单的性能测试:


在一个简答查询接口中,性能提升一倍;


在一个略复杂接口中,执行4、5个查询,加入缓存后性能提升20倍。


在这里就不贴ab测试结果了,大家可以自行测试一下。


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇awk转义序列与算术操作符 下一篇计算机中的黑魔法:尾递归

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: