引用
缓存就是存贮数据(使用频繁的数据)的临时地方,因为取原始数据的代价太大了,所以我可以取得快一些。
1、一级缓存与二级缓存的差异
1)二级缓存默认关闭,一级缓存默认开启,二级缓存以Mapper的namespace为单位,但是一级缓存以sqlsession为单位,如果采用Spring管理对象,那么每次一个事务就会有一个sqlsession。
2)二级缓存的读取都采用了锁控制并发,但是一级缓存并没有,而且Mybatis强调了sqlsession不应该多线程共享,看到这里确实是有道理的,第一个是sqlsession关闭了在使用会报错,其二是读写缓存数据都没有加锁;然而,二级缓存虽然是建立在一级缓存之上,但是二级缓存采用了SynchronizedCache缓存,对数据的读写都进行了加锁,整个二级缓存就是一个责任链模式,从 SynchronizedCache(读写加锁)——>LoggingCache(命中率记录)——>SerializedCache(缓存值序列化、反序列化)——>LruCache(移除无用缓存)——>PerpetualCache(一级缓存,缓存数据的存储);
3)二级缓存采用的Executor是BaseExecutor;二级缓存采用的Executor是CachingExecutor(内部委托BaseExecutor进行数据库操作);
2、一级缓存代码
if (cachedList != null) {
list = cachedList;
} else {
try {
list = doQuery(ms, parameter, rowBounds, resultHandler);
} finally {
localCache.removeObject(key);
}
localCache.putObject(key, list);
}
} finally {
queryStack--;
}
if (queryStack == 0) {
for (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
}
return list;
}
3、一级缓存的理解
所谓一级缓存,就是在一次会话当中,有可能重复执行完全相同的查询语句,为了避免数据库的压力,所以采用缓存的方式,第一次查询的数据放在缓存,第二次直接从缓存中获取数据,注意Java返回的是对象的引用,缓存的也是对象的引用,所以这个对象是可write的。PerpetualCache 就是一级缓存的实现。
一级缓存是一个粗粒度的缓存,没有更新缓存和缓存过期的概念,对于一些隔离级别低的数据库,比如一个事务在查询数据时,另一个事务还可以进行对数据库操作,那么导致前者读出的数据其实是过时数据,那么这个时候的缓存就是有问题的,比如数据库隔离级别是 Read Committed , 那么两次读取的数据可能是不一致的(不可重复读),可是由于缓存将会导致每次得到的数据都是一致的。
4、二级缓存代码
if (cache != null) {
flushCacheIfRequired(ms);
try {
if (ms.isUseCache()) {
CacheKey key = createCacheKey(ms, parameterObject, rowBounds);
final List cachedList = (List) cache.getObject(key);
if (cachedList != null) {
return cachedList;
} else {
List list = delegate.query(ms, parameterObject, rowBounds, resultHandler);
tcm.putObject(cache, key, list);
return list;
}
} else {
return delegate.query(ms, parameterObject, rowBounds, resultHandler);
}
} finally {
}
}
}
return delegate.query(ms, parameterObject, rowBounds, resultHandler);
}
5、二级缓存理解
CachingExecutor: 二级缓存执行器。灵活地使用 delegate机制。其委托执行的类是 BaseExcutor。 当无法从二级缓存获取数据时,同样需要从 DB 中进行查询,于是在这里可以直接委托给 BaseExcutor 进行查询。一级缓存就涉及到一个类PerpetualCache ,然而二级缓存则是一个责任链模式的结构,可以通过配置文件指定需要的缓存类
6、二级缓存的设置
在Mapper文件中配置开启二级缓存
<cache
eviction="FIFO"
flushInterval="600000" size="512"
readOnly="true"
/>
来源:oschina
链接:https://my.oschina.net/u/1989321/blog/618120