--- title: 分布式多级缓存 tags: [多级缓存, Cache] sidebar_position: 10 slug: /advanced-guide/layering-cache --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 分布式多级缓存 盘古开发框架基于[Laying Cahce](https://github.com/xiaolyuh/layering-cache),提供支持分布式环境的多级缓存功能。使用Caffeine作为一级本地缓存,Redis作为二级集中式缓存。支持缓存信息监控统计、支持缓存过期时间在注解上直接配置、支持缓存的自动刷新、缓存Key支持SpEL表达式、支持无感禁用一级缓存或二级缓存。通过缓存空值来解决缓存穿透问题、通过异步加载缓存的方式来解决缓存击穿和雪崩问题。 ## 安装相关盘古模块 ```jsx com.gitee.pulanos.pangu pangu-parent latest.version.xxx ``` ```jsx com.gitee.pulanos.pangu pangu-spring-boot-starter ``` ```jsx com.gitee.pulanos.pangu pangu-cache-spring-boot-starter ``` ## 本地配置 > 为便于理解,本文基于本地配置的方式编写。若改为标准的Nacos配置中心模式,请参阅:[使用指南->配置中心](/docs/advanced-guide/nacos-config-center)章节。 ```jsx spring.profiles.active=${spring.profiles.active:dev} ``` ```jsx 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.serializer | Redis序列化方式 ## 基于注解声明 直接在需要缓存的方法上加上`@Cacheable`、`@CacheEvict`、`@CachePut`注解。(`@FirstCache`、`@SecondaryCache`为注解配置项,不能单独使用) ### @FirstCache 一级缓存配置项。 名称 | 默认值 | 说明 --- | --- | --- initialCapacity | 10 | 缓存初始Size maximumSize | 5000 | 缓存最大Size expireTime | 9 | 缓存有效时间 timeUnit | TimeUnit.MINUTES | 时间单位,默认分钟 expireMode | ExpireMode.WRITE | 缓存失效模式,ExpireMode.WRITE:最后一次写入后到期失效,ExpireMode.ACCESS:最后一次访问后到期失效 ### @SecondaryCache 二级缓存配置项。 名称 | 默认值 | 说明 --- | --- | --- expireTime | 5 | 缓存有效时间 preloadTime | 1 | 缓存主动在失效前强制刷新缓存的时间,建议是 expireTime * 0.2 timeUnit | TimeUnit.HOURS | 时间单位,默认小时 forceRefresh | false | 是否强制刷新(直接执行被缓存方法) magnification | 1 | 非空值和null值之间的时间倍率,默认是1。如expireTime=60秒,magnification=10,那么当缓存空值时,空值的缓存过期时间是60/10=6秒。 ### @Cacheable 表示用的方法的结果是可以被缓存的,当该方法被调用时先检查缓存是否命中,如果没有命中再调用被缓存的方法,并将其返回值放到缓存中。 名称 | 默认值 | 说明 --- | --- | --- cacheNames | 空字符串数组 | 缓存名称 key | 空字符串 | 缓存key,支持SpEL表达式 depict | 空字符串 | 缓存描述(在缓存统计页面会用到) enableFirstCache | true | 是否启用一级缓存 firstCache | | 一级缓存配置 secondaryCache | | 二级缓存配置 ```jsx title="@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 | 空字符串 | 缓存描述(在缓存统计页面会用到) enableFirstCache | true | 是否启用一级缓存 firstCache | | 一级缓存配置 secondaryCache | | 二级缓存配置 ```jsx title="@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表达式 allEntries | false | 是否删除缓存中所有数据,默认情况下是只删除关联key的缓存数据,当该参数设置成 true 时 key 参数将无效 ```jsx title="@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`注解的加持。如下代码所示。 ```jsx {1} @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 cahce相互隔离的,你只要在配置文件加入Spring Cache的配置,就可以注入RedisTemplate直接使用了。可以单独使用,也可以和laying cache混合使用。具体用法可以参考范例:pangu-examples-cache-single。
## 相关参考范例 - [pangu-examples-cache-layering](https://gitee.com/pulanos/pangu-framework/tree/master/pangu-examples/pangu-examples-empty-web):两级缓存(本地缓存+Redis集中缓存)范例 - [pangu-examples-cache-single](https://gitee.com/pulanos/pangu-framework/tree/master/pangu-examples/pangu-examples-cache-single):Spring Cache一级缓存API(RedisTemplate)范例 ## 下一步 继续阅读其它章节获取您想要的答案或通过我们的[开发者社区](/docs/community)寻求更多帮助。