数据缓存策略
(一)hibernate数据缓存策略
缓存是数据库数据在内存中的临时容器,它包含了库表数据在内存中的拷贝,位于数据库与数据访问层之间。对于查询操作相当频繁的系统(论坛,新闻发布等),良好的缓存机制显得尤为重要。
ORM在进行数据读取时,首先在缓存中查询,避免了数据库调用的性能开销。
ORM的数据缓存应包含下面几个层次:
1)事务级缓存 2)应用级缓存 3)分布式缓存
具体针对Hibernate而言,采用两级缓存策略,其过程描述:
(1)条件查询的时候,总是发出一条select * from table_name where …. 这样的SQL语句查询数据库,一次获得所有的数据对象。
(2) 把获得的所有数据对象根据ID放入到第二级缓存中。
(3) 当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;查不到,再查询数据库,把结果按照ID放入到缓存。
(4) 删除、更新、增加数据的时候,同时更新缓存。
1. 一级缓存(session level)-数据库事务级缓存
1)根据主键id加载数据时。 Session.load(), Session.iterate()方法
2)延迟加载时
Session内部维护一个数据对象集合,包括了本Session内选取的、操作的数据对象。这称为Session内部缓存,是Hibernate的第一级最快缓存,属于Hibernate的既定行为,不需要进行配置(也没有办法配置 :-)。
内部缓存正常情况下由hibernate自动维护,但也可人工干预:
1) Session.evict (): 将某个特定对象从内部缓存中清除
2)Session.clear(): 清空内部缓存
2.二级缓存(SessionFactory level)-应用级缓存
二级缓存由SessionFactory的所有session实例共享。
3. 第三方缓存实现
EHCache, OSCahe
hibernate批量查询引起的内存溢出问题
批量查询基本不适合使用现有的持久层技术来做,如CMP或hibernate,IBatis倒是可以.
因为每次调用Session.save()方法时,当前session都会将对象纳入到自身的内部缓存中。内部缓存不同于二级缓存,我们可以在二级缓存的配置中指定其最大容量。
解决方案:
1)在批处理情况下,关闭Hibernate缓存,如果关闭Hibernate缓存,那么和直接使用JDBC就没有区别。
2) 每隔一段时间清空Session内部缓存
Session实现了异步write-behind,它允许Hibernate显式地写操作的批处理。 这里,我给出Hibernate如何实现批量插入的方法: 首先,我们设置一个合理的JDBC批处理大小,hibernate.jdbc.batch_size 20。 然后在一定间隔对Session进行flush()和clear()。
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000>
Customer customer = new Customer(.....);
session.save(customer);
if ( i % 20 == 0 ) {
//flush 插入数据和释放内存:
session.flush(); session.clear(); }
}
tx.commit();
session.close();
为了优化性能,可执行批量操作。在传统的JDBC编程中,批量操作方式如下,将数个SQL操作批量提交:
PrepareStatement ps=conn.prepareStatement("insert into users(name) values(?)");
for(int i=0;i<100000>
ps.setString(1, "user"+i);
ps.addBatch();
}
int[] counts=ps.executeBatch
在Hibernate中,可以设置hibernate.jdbc.batch_size 参数来指定每次提交的sql数量。
hibernate2和hibernate3数据批量删除机制分析
1.hibernate2
Transaction tx=session.beginTransaction();
session.delete("from users");
tx.commit();
观察日志输出:
select ... from users
Hibernate:delete from users where id=?
Hibernate:delete from users where id=?
Hibernate:delete from users where id=?
...
hibernate2版本会首先从数据库中查询出所有符合条件的记录,再对此记录循环删除。如果记录量过大,势必引起内存溢出和删除效率问题。ORM为什么要这么做呢?因为ORM为了自动维护内存状态,必须知道用户到底对哪些数据进行了操作。问题的解决方法:
1)内存消耗
批量删除前首先从数据库中查询出所有符合条件的记录,如果数据量过大,就会导致 OutOfMemoryError.
可以采用Session .iterate或Query.iterate方法逐条获取记录,再执行delete操作。另外,hibernate2.16后的版本提供了基于游标的数据遍历操作:
Transaction tx=session.beginTransaction();
String hql="from users";
Query query=session.createQrery(hql);
ScrollableResults sr=query.scroll();
while(sr.next()){
TUser user=(TUser)sr.get(0);
session.delete();
}
tx.commit();
2)循环删除的效率问题
由于hibernate在批量删除操作过程中,需要反复调用delete SQL,存在性能问题。我们仍然可以通过调整hibernate.jdbc.batch_size参数来解决。
2.hibernate3
hibernate3 HQL中引入了 bulk delete/update操作, 即通过一条独立的sql语句来完成数据的批量操作。
Transaction tx=session.beginTransaction();
String hql="delete TUser";
Query query=session.createQrery(hql);
int count=query.executeUpdate();
tx.commit();
观察日志输出:
Hibernate:delete from TUser
(二)ibatis数据缓存
相对Hibernate 等封装较为严密的ORM 实现而言(因为对数据对象的操作实现了较为严密的封装,可以保证其作用范围内的缓存同步,而ibatis 提供的是半封闭的封装实现,因此对缓存的操作难以做到完全的自动化同步)。 ibatis 的缓存机制使用必须特别谨慎。特别是flushOnExecute 的设定(见“ibatis配置”一节中的相关内容),需要考虑到所有可能引起实际数据与缓存数据不符的操作。如本模块中其他Statement对数据的更新,其他模块对数据的更新,甚至第三方系统对数据的更新。否则,脏数据的出现将为系统的正常运行造成极大隐患。如果不能完全确定数据更新操作的波及范围,建议避免Cache的盲目使用。1.iBatis cache设置sqlmap-config.xml在里面加入
cacheModelsEnabled="true"
enhancementEnabled="true"
lazyLoadingEnabled="true" />
maps.xml在里面加入
<cacheModel id="userCache" type="LRU" readonly="true" serialize="false">
可以看到,Cache有如下几个比较重要的属性:readOnly,serialize,type
readOnly
readOnly值的是缓存中的数据对象是否只读。这里的只读并不是意味着数据对象一
旦放入缓存中就无法再对数据进行修改。而是当数据对象发生变化的时候,如数据对
象的某个属性发生了变化,则此数据对象就将被从缓存中废除,下次需要重新从数据
库读取数据,构造新的数据对象。
serialize
如果需要全局的数据缓存,CacheModel的serialize属性必须被设为true。否则数据缓存只对当前Session(可简单理解为当前线程)有效,局部缓存对系统的整体性能提升有限。
Cache Type:
与hibernate类似,ibatis通过缓冲接口的插件式实现,提供了多种Cache的实现机制可供选择:
1. MEMORY
2. LRU
3. FIFO
4. OSCACHE
MEMORY类型Cache与WeakReference
MEMORY 类型的Cache 实现,实际上是通过Java 对象引用进行。ibatis 中,其实现类
为com.ibatis.db.sqlmap.cache.memory.MemoryCacheController,MemoryCacheController 内部,
使用一个HashMap来保存当前需要缓存的数据对象的引用。
LRU型Cache
当Cache达到预先设定的最大容量时,ibatis会按照“最少使用”原则将使用频率最少
的对象从缓冲中清除。可配置的参数有:
flushInterval:指定了多长时间清除缓存,上例中指定每24小时强行清空缓存区的所有内容。
size
FIFO型Cache
先进先出型缓存,最先放入Cache中的数据将被最先废除。
OSCache
(三)开源数据缓存策略OSCache
可以解决的问题:
1)信息系统中需要处理的基础数据的内容短时间内是不会发生变化的,但是在一个相对长一些的时间里,它却可能是动态增加或者减少的。
2)统计报表是一个周期性的工作,可能是半个月、一个月或者更长的时间才会需要更新一次,然而统计报表通常是图形显示或者是生成pdf、word、excel等格式的文件,这些图形内容、文件的生成通常需要消耗很多的系统资源,给系统运行造成很大的负担。
OSCache是OpenSymphony组织提供的一个J2EE架构中Web应用层的缓存技术实现组件。OSCache支持对部分页面内容或者对页面级的响应内容进行缓存,编程者可以根据不同的需求、不同的环境选择不同的缓存级别。可以使用内存、硬盘空间、同时使用内存和硬盘或者提供自己的其他资源(需要自己提供适配器)作为缓存区。
使用步骤:
1. 下载、解压缩OSCache
请到OSCache的主页http://www.opensymphony.com/oscache/download.html下载Oscache的最新版本,作者下载的是OSCache的最新稳定版本2.0。
将下载后的。Zip文件解压缩到c:\oscache(后面的章节中将使用%OSCache_Home%来表示这个目录)目录下
2. 新建立一个web应用
3. 将主要组件%OSCache_Home%\oscache.jar放入WEB-INF\lib目录
4. commons-logging.jar、commons-collections.jar的处理
OSCache组件用Jakarta Commons Logging来处理日志信息,所以需要commons-logging.jar的支持,请将%OSCache_Home%\lib\core\commons-logging.jar放入classpath(通常意味着将这个文件放入WEB-INF\lib目录)
如果使用JDK1.3,请将%OSCache_Home%\lib\core\commons-collections.jar放入classpath,如果使用JDK1.4或者以上版本,则不需要了
5. 将oscache.properties、oscache.tld放入WEB-INF\class目录
%OSCache_Home%\oscache.properties包含了对OSCache运行特征值的设置信息
%OSCache_Home%\oscache.tld包含了OSCache提供的标签库的定义内容
6. 修改web.xml文件
在web.xml文件中增加下面的内容,增加对OSCache提供的taglib的支持:
oscache/WEB-INF/classes/oscache.tld
7.最简单的cache标签用法
使用默认的关键字来标识cache内容,超时时间是默认的3600秒
<%//自己的JSP代码内容%>
8. 缓存单个文件
在OSCache组件中提供了一个CacheFilter用于实现页面级的缓存,主要用于对web应用中的某些动态页面进行缓存,尤其是那些需要生成pdf格式文件/报表、图片文件等的页面,不仅减少了数据库的交互、减少数据库服务器的压力,而且对于减少web服务器的性能消耗有很显著的效果。
修改web.xml,增加如下内容,确定对/testContent.jsp页面进行缓存。
CacheFiltercom.opensymphony.oscache.web.filter.CacheFilterCacheFilter<!-对/testContent.jsp页面内容进行缓存--> /testContent.jsp
分享到:
相关推荐
提出了以四叉树作为缓存数据结构,结合广泛应用的LRU和LFU算法,给出了一种高效的缓存策略—基于四叉树的空间数据缓存策略,并详细描述了缓存框架和缓存策略。提出的缓存策略充分考虑了空间数据访问所具有的时间局部...
提出了一种结合内存缓存与磁盘缓存的新型缓存策略.该策略在原有内存缓存基础上增加了磁盘缓存,数据从内存中被淘汰时,从磁盘缓存空间中选择合适磁盘分片进行缓存,并建立索引管理已缓存数据,使对等网络中的节点...
为提高P2P空间矢量数据索引网络的性能,在已有混合结构P2P空间索引网络的基础上,引入缓存机制,并提出了一种新的面向多图层的空间矢量数据缓存更新策略。该策略针对空间矢量数据多图层特性,综合考虑图层优先级以及...
该程序包提供了一个抽象层,用于使用Eloquent模型轻松实现行业标准的缓存策略。 缓存方法概述 实施缓存策略 旁读 直读 直写 回写 漂亮查询 缓存无效技术 保存缓存存储 保持缓存一致性 异常处理 数据库异常 缓存存储...
缓存是介于应用程序和物理数据之间的,其作用是为了降低应用程序对物理数据访问的频次从而提高应用系统的性能。缓存思想的提出主要是因为对物理数据的访问效率要远远低于对内存的访问速度,因而采用了将部分物理数据...
针对NDN(命名数据网络)中确定性缓存和概率性缓存进行研究,提出一种确定性缓存和概率性缓存相结合的混合式NDN缓存策略(HDP)。基于区域划分的思想,在网络边缘采用基于热度的确定性缓存策略,在网络核心采用基于...
针对以上研究提出一种基于Alluxio远程场景下的缓存策略CPR,利用存储系统中数据块之间的关联性指导数据预取与替换,采用分组思想提高关联规则的利用率,启用后台线程实时更新规则集,并通过仿真实验验证策略的有效性...
基于移动边缘计算的车联网缓存策略研究.pdf
NDN中基于深度学习的缓存策略的研究与实现,孙明欣,李文生,命名数据网络(Named Data Networking, NDN)作为新型的网络体系结构,网内缓存是其一大特色,也是提高其效率的重要组成部分。为了解决目�
实现redis缓存策略和Spring集成redis配置 1.1 Redis是一个key-value存储系统,支持多种存储结构,如String,Hash,list,zset等; 1.2 Redis采用内存中数据集的形式,因此读写性能优异; 1.3 Redis支持数据持久化,支持...
网络游戏-命名数据移动自组织网络的官渡缓存策略.zip
缓存数据来源是预知的,我们可以预先定义哪些 mutation 是缓存相关的。 我们期望这个过程更自然一点,通过某种变化自动映射,使以后不管缓存类别增加还是减少都能修改极少的代码来应对变化。 Vuex的插件可以拦截 ...
车联网中基于NDN的缓存策略综述.pdf
提出考虑内容异构5G无线网络云对边混合缓存策略,设计优化了内容缓存位置,其可以是原始内容服务器、云单元(CUs)和基站(BSs)。采用Lyapunov优化方法解决了NP-hard缓存控制问题与CU缓存和BS缓存控制决策之间的...
此外,为了提升用户体验,还会涉及到图片优化、数据缓存策略、网络请求优化等技术细节。总之,综上所述,基于微信平台的在线漫画阅读小程序旨在提供一个内容丰富、操作便捷、社交性强的移动漫画阅读平台,满足现代...
提出一种应用于矿区通信的异构移动对等网络启发式路径缓存策略。这种策略具有强节点优先特性,适应于矿区通信中使用的异质移动计算环境的路径缓存策略。策略的核心是通过使用路径缓存来帮助节点寻找具有请求的数据的...
Levenblog为一个完整的使用.Net2.0(C#)开发的单用户Blog系统,系统拥有完善的Blog发布,评论,TrackBack...3.修改部分局部数据缓存策略以适应新的反射框架和新的事务策略 默认用户名和密码 用户名:leven 默认密码:admin888
使用的外部API是: (使用性能缓存策略) (使用新鲜度缓存策略)1.更新npm库首先安装或更新本地项目的npm依赖项: npm install2.运行生产版本执行生产版本: ng build --prod 该命令将生成一个dist / angular-pwa...
基于用户满意度的\网络视频缓存策略,权国聪,张文逸,随着用户对视频数据需求的爆炸性增长,无线网络中的缓存技术将发挥越来越大的作用。将视频放置在离用户较近的缓存中,避免了重复数�
并行计算框架Spark缺乏有效缓存选择机制,不能自动识别并缓存高重用度数据;缓存替换算法采用LRU,度量方法不够细致,影响任务的执行效率.本文提出一种Spark框架自适应缓存管理策略(Self-Adaptive Cache Management,SACM...