Skip to main content

分布式多级缓存

盘古开发框架基于 Laying Cahce,提供支持分布式环境的多级缓存功能。使用 Caffeine 作为一级本地缓存,Redis 作为二级集中式缓存。支持缓存信息监控统计、支持缓存过期时间在注解上直接配置、支持缓存的自动刷新、缓存 Key 支持 SpEL 表达式、支持无感禁用一级缓存或二级缓存。通过缓存空值来解决缓存穿透问题、通过异步加载缓存的方式来解决缓存击穿和雪崩问题。

安装相关盘古模块

<parent>
<groupId>com.gitee.pulanos.pangu</groupId>
<artifactId>pangu-parent</artifactId>
<version>latest.version.xxx</version>
<relativePath/>
</parent>

本地配置

为便于理解,本文基于本地配置的方式编写。若改为标准的 Nacos 配置中心模式,请参阅:配置中心 章节。

spring.application.name=pangu-examples-cache-layering

# layering-cache 多级缓存
layering-cache.stats=false
# redis单机
layering-cache.redis.database=1
layering-cache.redis.host=localhost
layering-cache.redis.port=6379
layering-cache.redis.password=
# redis集群
#layering-cache.redis.password=
#layering-cache.redis.cluster=127.0.0.1:6379,127.0.0.1:6378
layering-cache.redis.serializer=com.github.xiaolyuh.redis.serializer.JacksonRedisSerializer

logging.level.root=INFO
logging.level.com.gitee.pulanos.pangu=INFO

关键配置项说明

配置项
配置说明
layering-cache.stats缓存监控统计开关,缺省true
layering-cache.redis.serializerRedis序列化方式

基于注解声明

直接在需要缓存的方法上加上 @Cacheable@CacheEvict@CachePut 注解。( @FirstCache@SecondaryCache 为注解配置项,不能单独使用)

@FirstCache

一级缓存配置项。

名称默认值说明
initialCapacity10缓存初始 Size
maximumSize5000缓存最大 Size
expireTime9缓存有效时间
timeUnitTimeUnit.MINUTES时间单位,默认分钟
expireModeExpireMode.WRITE缓存失效模式,ExpireMode.WRITE:最后一次写入后到期失效,ExpireMode.ACCESS:最后一次访问后到期失效

@SecondaryCache

二级缓存配置项。

名称默认值说明
expireTime5缓存有效时间
preloadTime1缓存主动在失效前强制刷新缓存的时间,建议是 expireTime * 0.2
timeUnitTimeUnit.HOURS时间单位,默认小时
forceRefreshfalse是否强制刷新(直接执行被缓存方法)
magnification1非空值和 null 值之间的时间倍率,默认是 1。如 expireTime=60 秒,magnification=10,那么当缓存空值时,空值的缓存过期时间是 60/10=6 秒。

@Cacheable

表示用的方法的结果是可以被缓存的,当该方法被调用时先检查缓存是否命中,如果没有命中再调用被缓存的方法,并将其返回值放到缓存中。

名称默认值说明
cacheNames空字符串数组缓存名称
key空字符串缓存 key,支持 SpEL 表达式
depict空字符串缓存描述(在缓存统计页面会用到)
enableFirstCachetrue是否启用一级缓存
firstCache一级缓存配置
secondaryCache二级缓存配置
@Cacheable 范例代码
@Cacheable(cacheNames = "user", key = "#userId",
firstCache = @FirstCache(expireTime = 5),
secondaryCache = @SecondaryCache(expireTime = 10))
public UserVO getUser(Long userId) {
log.info("执行AnnotationBasedDemoService.getUser()");
// 从DB或其它资源渠道获取数据
UserVO userVO = new UserVO();
userVO.setId(userId);
userVO.setName("钱学森");
return userVO;
}

@CachePut

将数据放到缓存中,新增缓存。

名称默认值说明
cacheNames空字符串数组缓存名称
key空字符串缓存 key,支持 SpEL表达式
depict空字符串缓存描述(在缓存统计页面会用到)
enableFirstCachetrue是否启用一级缓存
firstCache一级缓存配置
secondaryCache二级缓存配置
@CachePut 范例代码
@CachePut(cacheNames = "user", key = "#userVO.id",
firstCache = @FirstCache(expireTime = 10),
secondaryCache = @SecondaryCache(expireTime = 30))
public UserVO saveUser(UserVO userVO) {
log.info("执行AnnotationBasedDemoService.saveUser()");
return userVO;
}

@CacheEvict

删除缓存。

名称默认值说明
value空字符串数组缓存名称,cacheNames 的别名
cacheNames空字符串数组 缓存名称
key空字符串缓存 key,支持 SpEL 表达式
allEntriesfalse是否删除缓存中所有数据,默认情况下是只删除关联 key 的缓存数据,当该参数设置成 true 时 key 参数将无效
@CacheEvict 范例代码
@CacheEvict(cacheNames = "user", key = "#userId")
public void delUser(Long userId) {
log.info("执行AnnotationBasedDemoService.delUser()");
}

@CacheEvict(cacheNames = "user", allEntries = true)
public void delAllUsers() {
log.info("执行AnnotationBasedDemoService.delAllUsers()");
}

基于 API 编程

可以直接使用 Laying Cahce 提供的 API 进行硬编码操作两级缓存,但不建议使用。这里就不做详细讲解了,可以在参考范例的 ApiBasedDemoService 类中找到相关的代码。

启动入口

需要 @EnableLayeringCache 注解的加持。如下代码所示。

@EnableLayeringCache
@SpringBootApplication
public class LayeringCachePanguApplication {
public static void main(String[] args) {
PanGuApplicationBuilder.init(LayeringCachePanguApplication.class).run(args);
}
}
快速 QA:可以禁用一级缓存,只使用二级缓存吗?
必须可以。设置 enableFirstCache = false 即可。
快速 QA:可以禁用二级缓存,只使用一级缓存吗?
可以。设置二级缓存 expireTime 为 0 即可。
快速 QA:我可以用 Spring Cache 的 RedisTemplate API 吗?
可以。Laying Cache 和 Spring Cache 相互隔离的,你只要在配置文件加入 Spring Cache 的配置,就可以注入 RedisTemplate 直接使用了。可以单独使用,也可以和 Laying Cache 混合使用。具体用法可以参考范例:pangu-examples-cache-single。

本文相关范例源码

下一步

继续阅读其它章节获取你想要的答案或通过我们的 开发者社区 寻求更多帮助。