Mybatis 缓存学习

蹲街弑〆低调 提交于 2019-11-28 14:27:47


引用

缓存就是存贮数据(使用频繁的数据)的临时地方,因为取原始数据的代价太大了,所以我可以取得快一些。


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"

    />


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!