介绍

自动将baseMapper.selectById(id)lambdaQuery().eq(Entity::getId, id)listByIds(ids)等方式通过主键或主键集合查询的对象结果,自动将查询结果缓存到Redis中。

缓存对象默认1天(上下浮动10%),数据库中没有的数据也会缓存一个NULL值(1分钟有效期)。避免缓存穿透和雪崩。

数据删除、更新时会自动清除缓存(removeByIdupdateByIdupdate等方法,如果使用lambdaUpdate则仅限于通过主键方式更新lambdaUpdate().eq(BookEmbeddings::getId, 8)

源码

RedisCacheInterceptor.java

原理

  1. 实现org.apache.ibatis.plugin.Interceptor接口,拦截selectupdate操作。
  2. 分析MappedStatement的参数,找到操作的对象类型和主键。
  3. 对于查询操作,使用RedisTemplate缓存查询结果。
  4. 对于更新操作,清除相关的缓存。
  5. 支持批量查询和单个查询,自动处理主键集合。使用mget批量获取redis中已有缓存数据,缓存中没有的数据则通过手动构建new Invocation(invocation.getTarget(), invocation.getMethod(), newArgs).proceed()方式查询数据库。并将查询结果缓存到Redis中。

注意

必须是通过主键对数据查询和更新,非主键或者多个字段查询不支持。按非主键条件更新数据也不支持。

可以先查询出主键id,再通过主键id批量查询数据,更新数据同理。

AI 介绍稿

基于MyBatis拦截器机制实现的二级缓存,使用Redis作为缓存存储。 支持以下功能:

单条记录的主键查询缓存

  • 批量查询的mget优化(兼容Redis Cluster)
  • 更新操作的缓存失效
  • 空值缓存防穿透
  • 双删策略保证数据一致性

支持的查询类型:

  • 简单主键等值查询:baseMapper.selectById(id)
  • LambdaQueryWrapper单主键查询:lambdaQuery().eq(Entity::getId, id)
  • 批量主键查询:baseMapper.selectBatchIds(ids)

缓存策略:

  • 缓存键格式:{完整类名}:主键值(使用Hash Tag确保Cluster兼容性,避免同名类冲突)
  • 正常数据缓存时间:1天(带随机浮动±2.4小时,防止缓存雪崩)
  • 空值缓存时间:1分钟(带随机浮动±6秒,防止缓存穿透)
  • 浮动过期时间:在基础过期时间上增加±10%的随机时间,避免大量缓存同时过期

Redis Cluster兼容性:

  • 使用Hash Tag语法确保同一实体类的key在同一槽位
  • 批量操作优先使用multiGet,失败时自动回退到逐个获取
  • 完全兼容单机Redis和Redis Cluster部署
  • 更新时采用双删策略:操作前删除 -> 执行数据库操作 -> 操作后再删除