MyBatis 一级二级和自定义缓存

2020-12-18 From 程序之心 By 丁仪

缓存是 MyBatis 的重要功能。使用缓存可以减低数据查询次数,对性能有较大的提升。MyBatis 提供了一级缓存和二级缓存,但是可能存在脏数据问题,使用时需要谨慎评估。如有需要可以自定义缓存来规避脏数据问题

一级缓存

一级缓存主要用于在一次数据库会话中多次执行查询条件完全相同的 SQL 语句,MyBatis 会优先命中一级缓存降低对数据库的直接查询次数,一级缓存的最大生效范围是 SqlSession 内部。一级缓存默认是开启的。

MyBatis 中 SqlSession 持有 Executor,每个 Executor 都有 LocalCache。在一次会话中,如果有修改数据的 SQL,比如执行了 update 语句,一级缓存默认会失效。

MyBatis 根据查询语句生成 MappedStatement,首先在 LocalCache 中进行查询,如果命中就直接返回;如果没有命中,才去查询数据库,并把查询到的数据结果写入 LocalCache。一级缓存 LocalCache 实际上是使用 HashMap 实现的。

开启一级缓存的配置方式是设置 setting。value 可选值是 SESSION 和 STATEMENT,默认是 SESSION。

二级缓存

如果需要在多个 SqlSession 之间共享缓存,则需要使用二级缓存。二级缓存默认关闭,需要手动配置开启。开启二级缓存后,会使用 CachingExecutor 装饰 Executor,在进入一级缓存查询流程前,先在 CachingExecutor 进行二级缓存查询。二级缓存的 POJO 对象必须可以序列化,需要实现 Serializable 接口

同一个 namespace 下的所有操作语句,都影响着同一个 Cache。开启二级缓存后,所有 select 语句会被缓存,可以设置 useCache="false" 实现每次都访问 db 数据;insert、update、delete 语句会刷新缓存,可以设置 flushCache="false" 实现不刷新缓存

开启二级缓存的配置方式是设置 cache 标签。cache 标签有如下配置项:

eviction:回收策略,可选 FIFO(先进先出)、LRU(最近最少使用)、SOFT(软引用)、WEAK(弱引用),默认是 LRU;

flushInterval:缓存刷新时间(可以理解为超时时间),单位是毫秒,不配置则只有执行 SQL 时刷新;

size:缓存对象个数上限,默认 1024;

readOnly:是否只读,默认可读可写,也就是对缓存对象(实际是副本)的修改是安全的;

blocking:若缓存无法命中,是否会一直 blocking 直到有对应的数据进入缓存

在多表查询时,namspace 无法感知其他 namspace 对涉及的表的数据修改,因此可能会引起脏数据。在有需要的情况下,可以使用 cache ref 来引用其他 namspace 的缓存配置,实现两个 namspace 共用相同的缓存,但是缓存的粒度会变粗,数据操作都会对缓存有影响。

事务中,事务提交后才会对缓存有影响,事务回滚或者不提交不会对缓存有影响。

自定义缓存

前面的缓存都是本地缓存,在大型分布式系统中无法保证全局的一致性。可以使用 MyBatis 的自定义缓存能力进行扩展,把数据缓存在 Redis 或其他流行的缓存服务器中,来解决数据一致性问题。自定义缓存时,需要我们自己解决缓存的写入、读取、清除等功能。

自定义缓存需要实现 org.apache.ibatis.cache.Cache 接口,然后在 cache 标签中配置,属性是 type="你的缓存对象类型"。Cache 接口定义了 putObject、getObject、removeObject、clear、getSize、getReadWriteLock 几个方法,能够实现缓存数据的写入、查询、删除、计数等功能。

如果自定义缓存需要初始化参数,也可以在内使用进行配置。MyBatis 可以通过 setter 方法把配置参数传给实现类,完成实现类自定义的初始化。

总结

  • 一级缓存在 SqlSession 内部共享,二级缓存可以跨越多个 SqlSession;
  • 二级缓存可以管控到 namespace 级别,但是多表查询时,可能会出现脏数据
  • 本地缓存在有数据更新时才会失效,因此分布式情况下无法保证缓存同时失效,可能会出现脏数据
  • 单机应用或数据一致性要求不高时,设置合理的缓存有效期可以保证业务需求;
  • 分布式应用,可以使用自定义分布式缓存解决数据一致性问题

本文来源:程序之心,转载请注明出处!

本文地址:https://chengxuzhixin.com/blog/article/200063.html

发表感想

© 2016 - 2022 chengxuzhixin.com All Rights Reserved.

浙ICP备2021034854号-1    浙公网安备 33011002016107号