Hibernate性能优化之EHCache缓存

 2023-09-15 阅读 26 评论 0

摘要:像Hibernate这种ORM框架,相较于JDBC操作,需要有更复杂的机制来实现映射、对象状态管理等,因此在性能和效率上有一定的损耗。 在保证避免映射产生低效的SQL操作外,缓存是提升Hibernate的关键之一。 加入缓存可以避免数据库调用带来的连接创建与销毁

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

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

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

ehcache遍历数据。在考虑给系统加入缓存进行优化前,复用SessionFactory是Hibernate优化最优先、最基础的性能优化方法,参考上一篇《Hibernate性能优化之SessionFactory重用》。

Hibernate的缓存机制


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

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

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

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

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

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

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

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

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

为什么要直接使用EHCache


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

Hibernate的缓存模式是什么?

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

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

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

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

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

如何使用EHCache


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

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

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:noNamespaceSchemaLocation="ehcache.xsd">  <diskStore path="java.io.tmpdir"/>  <defaultCache  maxElementsInMemory="10000"  maxElementsOnDisk="0"  eternal="true"  overflowToDisk="true"  diskPersistent="false"  timeToIdleSeconds="0"  timeToLiveSeconds="0"  diskSpoolBufferSizeMB="50"  diskExpiryThreadIntervalSeconds="120"  memoryStoreEvictionPolicy="LFU"  />  <cache name="restCache"  maxElementsInMemory="100"  maxElementsOnDisk="0"  eternal="false"  overflowToDisk="false"  diskPersistent="false"  timeToIdleSeconds="119"  timeToLiveSeconds="119"  diskSpoolBufferSizeMB="50"  diskExpiryThreadIntervalSeconds="120"  memoryStoreEvictionPolicy="FIFO"  />  
</ehcache>  

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测试结果了,大家可以自行测试一下。


记录,为更好的自己!

转载于:https://www.cnblogs.com/ym123/p/4627435.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/55774.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息