Cache
        在特定硬件基础上(同时假设系统不存在设计上的缺漏和糟糕低效的SQL 语句)Cache往往是提升系统性能的最关键因素)。
        相对Hibernate 等封装较为严密的ORM 实现而言(因为对数据对象的操作实现了较为严密的封装,可以保证其作用范围内的缓存同步,而ibatis 提供的是半封闭的封装实现,因此对缓存的操作难以做到完全的自动化同步)。
        ibatis 的缓存机制使用必须特别谨慎。特别是flushOnExecute 的设定,需要考虑到所有可能引起实际数据与缓存数据不符的操作。如本模块中其他Statement对数据的更新,其他模块对数据的更新,甚至第三方系统对数据的更新。否则,脏数据的出现将为系统的正常运行造成极大隐患。
        如果不能完全确定数据更新操作的波及范围,建议避免Cache的盲目使用。
结合cacheModel来看:
<cacheModel
id="product-cache"
type ="LRU"
readOnly="true"
serialize="false">
</cacheModel>

可以看到,Cache有如下几个比较重要的属性:
  readOnly
  serialize
  type

readOnly
readOnly值的是缓存中的数据对象是否只读。这里的只读并不是意味着数据对象一旦放入缓存中就无法再对数据进行修改。而是当数据对象发生变化的时候,如数据对象的某个属性发生了变化,则此数据对象就将被从缓存中废除,下次需要重新从数据库读取数据,构造新的数据对象。
而readOnly="false"则意味着缓存中的数据对象可更新,如user 对象的name属性发生改变。
只读Cache能提供更高的读取性能,但一旦数据发生改变,则效率降低。系统设计时需根据系统的实际情况(数据发生更新的概率有多大)来决定Cache的读写策略。
serialize
如果需要全局的数据缓存,CacheModel的serialize属性必须被设为true。否则数据缓存只对当前Session(可简单理解为当前线程)有效,局部缓存对系统的整体性能提升有限。
在serialize="true"的情况下,如果有多个Session同时从Cache 中读取某个数据对象,Cache 将为每个Session返回一个对象的复本,也就是说,每个Session 将得到包含相同信息的不同对象实例。因而Session 可以对其从Cache 获得的数据进行存取而无需担心多线程并发情况下的同步冲突。
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来保存当前需要缓存的数据对象的引用。
这里需要注意的是Java2中的三种对象引用关系:
a SoftReference
b WeakReference
c PhantomReference

传统的Java 对象引用,如:
public void doSomeThing(){
User user = new User()
……
}

当doSomeThing方法结束时,user 对象的引用丢失,其所占的内存空间将由JVM在下次垃圾回收时收回。如果我们将user 对象的引用保存在一个全局的HashMap中,如:
Map map = new HashMap();
public void doSomeThing(){
User user = new User();
map.put("user",user);
}

此时,user 对象由于在map 中保存了引用,只要这个引用存在,那么JVM 永远也不会收回user 对象所占用的内存。
这样的内存管理机制相信诸位都已经耳熟能详,在绝大多数情况下,这几乎是一种完美的解决方案。但在某些情况下,却有些不便。如对于这里的Cache 而言,当user 对象使用之后,我们希望保留其引用以供下次需要的时候可以重复使用,但又不希望这个引用长期保存,如果每个对象的引用都长期保存下去的话,那随着时间推移,有限的内存空间将立即被这些数据所消耗殆尽。最好的方式,莫过于有一种引用方式,可以在对象没有被垃圾回收器回收之前,依然能够访问此对象,当垃圾回收器启动时,如果此对象没有被其他对象所使用,则按照常规对其进行回收。
SoftReference、WeakReference、PhantomReference为上面的思路提供了有力支持。
这三种类型的引用都属于“非持续性引用”,也就是说,这种引用关系并非持续存在,它们所代表的引用的生命周期与JVM 的运行密切相关,而非与传统意义上的引用一样依赖于编码阶段的预先规划。
先看一个SoftReference的例子:
SoftReference ref;
public void doSomeThing(){
User user = new User();
ref = new SoftReference(user);
}
public void doAnotherThing(){
User user = (User)ref.get();//通过SoftReference获得对象引用
System.out.println(user.getName());
}

假设我们先执行了doSomeThing 方法,产生了一个User 对象,并为其创建了一个SoftReference引用。
之后的某个时刻,我们调用了doAnotherThing方法,并通过SoftReference获取User 对象的引用。
        此时我们是否还能取得user 对象的引用?这要看JVM 的运行情况。对于SoftReference而言,只有当目前内存不足的情况下,JVM 在垃圾回收时才会收回其包含的引用(JVM 并不是只有当内存不足时才启动垃圾回收机制,何时进行垃圾回收取决于各版本JVM 的垃圾回收策略。如某这垃圾回收策略为:当系统目前较为空闲,且无效对象达到一定比率时启动垃圾回收机制,此时的空余内存倒可能还比较充裕)。这里可能出现两种情况,即:
? JVM 目前还未出现过因内存不足所引起的垃圾回收,user 对象的引用可以通过SoftReference从JVM Heap中收回。
? JVM 已经因为内存不足启动了垃圾回收机制,SoftReference所包含的user 对象的引用被JVM 所废弃。此时ref.get方法将返回一个空引用(null),对于上面的代码而言,也就意味着这里可能抛出一个NullPointerException。
WeakReference比SoftReference在引用的维持性上来看更加微弱。无需等到内存不足的情况,只要JVM 启动了垃圾回收机制,那么WeakReference所对应的对象就将被JVM 回收。
        也就是说,相对SoftReference而言,WeakReference 被JVM 回收的概率更大。PhantomReference 比WeakReference 的引用维持性更弱。与WeakReference 和SoftReference不同,PhantomReference所引用的对象几乎无法被回收重用。它指向的对象实际上已经被JVM 销毁(finalize方法已经被执行),只是暂时还没被垃圾回收器收回而已。
        PhantomReference主要用于辅助对象的销毁过程,在实际应用层研发中,几乎不会涉及。
MEMORY类型的Cache正是借助SoftReference、WeakReference以及通常意义上的Java Reference实现了对象的缓存管理。
        下面是一个典型的MEMORY类型Cache配置:
<cacheModel id="user_cache" type="MEMORY">
<flushInterval hours="24"/>
<flushOnExecute statement="updateUser"/>
<property name="reference-type" value="WEAK" />
</cacheModel>

其中flushInterval 指定了多长时间清除缓存,上例中指定每24 小时强行清空缓存区的所有内容。
reference-type属性可以有以下几种配置:
1. STRONG
即基于传统的Java对象引用机制,除非对Cache显式清空(如到了flushInterval设定的时间;执行了flushOnExecute所指定的方法;或代码中对Cache执行了清除操作等),否则引用将被持续保留。
此类型的设定适用于缓存常用的数据对象,或者当前系统内存非常充裕的情况。
2. SOFT
基于SoftReference 的缓存实现,只有JVM 内存不足的时候,才会对缓冲池中的数据对象进行回收。
此类型的设定适用于系统内存较为充裕,且系统并发量比较稳定的情况。
3. WEAK
基于WeakReference 的缓存实现,当JVM 垃圾回收时,缓存中的数据对象将被JVM收回。
一般情况下,可以采用WEAK的MEMORY型Cache配置。

LRU型Cache
当Cache达到预先设定的最大容量时,ibatis会按照“最少使用”原则将使用频率最少的对象从缓冲中清除。
<cacheModel id="userCache" type="LRU">
<flushInterval hours="24"/>
<flushOnExecute statement="updateUser"/>
<property name="size" value="1000" />
</cacheModel>

可配置的参数有:
u flushInterval
指定了多长时间清除缓存,上例中指定每24小时强行清空缓存区的所有内容。
u size
Cache的最大容量。
FIFO型Cache
先进先出型缓存,最先放入Cache中的数据将被最先废除。可配置参数与LRU型相同:
<cacheModel id="userCache" type="FIFO">
<flushInterval hours="24"/>
<flushOnExecute statement="updateUser"/>
<property name="size" value="1000" />
</cacheModel>

OSCache
与上面几种类型的Cache不同,OSCache来自第三方组织Opensymphony。可以通过以下网址获得OSCache的最新版本(http://www.opensymphony.com/oscache/)。在生产部署时,建议采用OSCache,OSCache 是得到了广泛使用的开源Cache 实现(Hibernate 中也提供了对OSCache 的支持),它基于更加可靠高效的设计,更重要的是,
最新版本的OSCache 已经支持Cache 集群。如果系统需要部署在集群中,或者需要部署在多机负载均衡模式的环境中以获得性能上的优势,那么OSCache在这里则是不二之选。
Ibatis中对于OSCache的配置相当简单:
<cacheModel id="userCache" type="OSCACHE">
<flushInterval hours="24"/>
<flushOnExecute statement="updateUser"/>
<property name="size" value="1000" />
</cacheModel>

之所以配置简单,原因在于,OSCache拥有自己的配置文件(oscache.properties)J。
下面是一个典型的OSCache配置文件:
#是否使用内存作为缓存空间
cache.memory=true
#缓存管理事件监听器,通过这个监听器可以获知当前Cache 的运行情况
cache.event.listeners=com.opensymphony.oscache.plugins.clustersupport.JMSBroa
dcastingListener
#如果使用磁盘缓存(cache.memory=false),则需要指定磁盘存储接口实现
#cache.persistence.class=com.opensymphony.oscache.plugins.diskpersistence.Disk
PersistenceListener
# 磁盘缓存所使用的文件存储路径
# cache.path=c:\\myapp\\cache
# 缓存调度算法,可选的有LRU,FIFO和无限缓存(UnlimitedCache)
IBATIS Developer’s Guide Version 1.0
September 2, 2004 So many open source projects. Why not Open your Documents?
# cache.algorithm=com.opensymphony.oscache.base.algorithm.FIFOCache
# cache.algorithm=com.opensymphony.oscache.base.algorithm.UnlimitedCache
cache.algorithm=com.opensymphony.oscache.base.algorithm.LRUCache
#内存缓存的最大容量
cache.capacity=1000
# 是否限制磁盘缓存的容量
# cache.unlimited.disk=false
# 基于JMS的集群缓存同步配置
#cache.cluster.jms.topic.factory=java:comp/env/jms/TopicConnectionFactory
#cache.cluster.jms.topic.name=java:comp/env/jms/OSCacheTopic
#cache.cluster.jms.node.name=node1
# 基于JAVAGROUP的集群缓存同步配置
#cache.cluster.properties=UDP(mcast_addr=231.12.21.132;mcast_port=45566;ip_
ttl=32;mcast_send_buf_size=150000;mcast_recv_buf_size=80000):PING(timeout
=2000;num_initial_members=3):MERGE2(min_interval=5000;max_interval=10000
):FD_SOCK:VERIFY_SUSPECT(timeout=1500):pbcast.NAKACK(gc_lag=50;retransm
it_timeout=300,600,1200,2400,4800):pbcast.STABLE(desired_avg_gossip=20000):
UNICAST(timeout=5000):FRAG(frag_size=8096;down_thread=false;up_thread=fal
se):pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;print_loc
al_addr=true)
#cache.cluster.multicast.ip=231.12.21.132
配置好之后,将此文件放在CLASSPATH 中,OSCache 在初始化时会自动找到此文件并根据其中的配置创建缓存实例。

ibatis的缓存机制的更多相关文章

  1. 深入浅出mybatis之缓存机制

    目录 前言 准备工作 MyBatis默认缓存设置 缓存实现原理分析 参数localCacheScope控制的缓存策略 参数cacheEnabled控制的缓存策略 总结 前言 提到缓存,我们都会不约而同 ...

  2. 《深入理解mybatis原理4》 MyBatis缓存机制的设计与实现

    <深入理解mybatis原理> MyBatis缓存机制的设计与实现 本文主要讲解MyBatis非常棒的缓存机制的设计原理,给读者们介绍一下MyBatis的缓存机制的轮廓,然后会分别针对缓存 ...

  3. MyBatis缓存机制-二级缓存

    MyBatis二级缓存是基于namespace级别的缓存. 1.MyBatis的缓存机制整体设计以及二级缓存的工作模式 如上图所示,当开一个会话时,一个SqlSession对象会使用一个Executo ...

  4. Mybatis学习系列(七)缓存机制

    Mybatis缓存介绍 MyBatis提供一级缓存和二级缓存机制. 一级缓存是Sqlsession级别的缓存,Sqlsession类的实例对象中有一个hashmap用于缓存数据.不同的Sqlsessi ...

  5. 《深入理解mybatis原理》 MyBatis缓存机制的设计与实现

    本文主要讲解MyBatis非常棒的缓存机制的设计原理,给读者们介绍一下MyBatis的缓存机制的轮廓,然后会分别针对缓存机制中的方方面面展开讨论. MyBatis将数据缓存设计成两级结构,分为一级缓存 ...

  6. Spring(五)Spring缓存机制与Redis的结合

    一.Redis和数据库的结合 使用Redis可以优化性能,但是存在Redis的数据和数据库同步的问题. 例如,T1时刻以将 key1 保存数据到 Redis,T2时刻刷新进入数据库,但是T3时刻发生了 ...

  7. mybatis的缓存机制及用例介绍

    在实际的项目开发中,通常对数据库的查询性能要求很高,而mybatis提供了查询缓存来缓存数据,从而达到提高查询性能的要求. mybatis的查询缓存分为一级缓存和二级缓存,一级缓存是SqlSessio ...

  8. mybatis深入理解(七)-----MyBatis缓存机制的设计与实现

    缓存设计 MyBatis将数据缓存设计成两级结构,分为一级缓存.二级缓存: 一级缓存是Session会话级别的缓存,位于表示一次数据库会话的SqlSession对象之中,又被称之为本地缓存.一级缓存是 ...

  9. Spring Boot从入门到精通(六)集成Redis实现缓存机制

    Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言 ...

随机推荐

  1. Kafka 温故(二):Kafka的基本概念和结构

    一.Kafka中的核心概念 Producer: 特指消息的生产者Consumer :特指消息的消费者Consumer Group :消费者组,可以并行消费Topic中partition的消息Broke ...

  2. ASP.NET MVC3-Music Store中英文教程 [下载]

    翻译原文档名: MVC Music Store版本: ASP.NET MVC3概述Mvc Music Store 是一个为WEB开发人员一步一步介绍和解释如何使用MVC和Visual Web开发的应用 ...

  3. 第7月第27天 c++11 boost

    1. #include <boost/asio.hpp> #include <cstdlib> #include <memory> namespace asio = ...

  4. 为什么mysqlbinlog --database选项不起作用

    群里看到有同学提问,多瞅了眼 [root@mysql55 mysql]# mysqlbinlog --no-defaults -vv --base64-output=decode-rows mysql ...

  5. AC自动机(病毒侵袭 )

    题目链接:https://cn.vjudge.net/contest/280743#problem/B 题目大意:中文题目 具体思路:AC自动机模板题,编号的时候注意,是按照给定的id进行编号的.然后 ...

  6. Python-Analysis-Malware

    Python恶意软件分析应用-PEfile 0x1.前言 要想对恶意代码快速分析,Python是一门必须要掌握的编程技能.因为它是跨平台的,而且容易阅读和编写.许多开源安全工具也是用Python写的. ...

  7. string替换所有指定字符串(C++)

    C++的string提供了replace方法来实现字符串的替换,但是对于将字符串中某个字符串全部替换这个功能,string并没有实现,我们今天来做的就是这件事. 首先明白一个概念,即string替换所 ...

  8. springboot日志框架

    Spring Boot日志框架Spring Boot支持Java Util Logging,Log4j2,Lockback作为日志框架,如果你使用starters启动器,Spring Boot将使用L ...

  9. activiti helloworld

    activiti helloworld activiti的入门实践文章,重点在于动手做,要解决的是怎么做的问题.只有知道了怎么做后,才具有实际动手能力,才算对这门技术有一个初步掌握:至于更深入细化的知 ...

  10. [转] caffe激活层及参数

    在激活层中,对输入数据进行激活操作(实际上就是一种函数变换),是逐元素进行运算的.从bottom得到一个blob数据输入,运算后,从top输入一个blob数据.在运算过程中,没有改变数据的大小,即输入 ...