1.背景
缓存,就是让数据更接近使用者,让访问速度加快,从而提升系统性能。工作机制大概是先从缓存中加载数据,如果没有,再从慢速设备(eg:数据库)中加载数据并同步到缓存中。
所谓多级缓存,是指在整个系统架构的不同系统层面进行数据缓存,以提升访问速度。主要分为三层缓存:网关nginx缓存、分布式缓存、本地缓存。这里的多级缓存就是用redis分布式缓存+caffeine本地缓存整合而来。
平时我们在开发过程中,一般都是使用redis实现分布式缓存、caffeine操作本地缓存,但是发现只使用redis或者是caffeine实现缓存都有一些问题:
- 一级缓存:Caffeine是一个一个高性能的 Java 缓存库;使用 Window TinyLfu 回收策略,提供了一个近乎最佳的命中率。优点数据就在应用内存所以速度快。缺点受应用内存的限制,所以容量有限;没有持久化,重启服务后缓存数据会丢失;在分布式环境下缓存数据数据无法同步;
- 二级缓存:redis是一高性能、高可用的key-value数据库,支持多种数据类型,支持集群,和应用服务器分开部署易于横向扩展。优点支持多种数据类型,扩容方便;有持久化,重启应用服务器缓存数据不会丢失;他是一个集中式缓存,不存在在应用服务器之间同步数据的问题。缺点每次都需要访问redis存在IO浪费的情况。
综上所述,我们可以通过整合redis和caffeine实现多级缓存,解决上面单一缓存的痛点,从而做到相互补足。
项目推荐:基于SpringBoot2.x、SpringCloud和SpringCloudAlibaba企业级系统架构底层框架封装,解决业务开发时常见的非功能性需求,防止重复造轮子,方便业务快速开发和企业技术栈框架统一管理。引入组件化的思想实现高内聚低耦合并且高度可配置化,做到可插拔。严格控制包依赖和统一版本管理,做到最少化依赖。注重代码规范和注释,非常适合个人学习和企业使用
Github地址:github.com/plasticene/…
Gitee地址:gitee.com/plasticene3…
微信公众号:Shepherd进阶笔记
交流探讨qun:Shepherd_126
2.整合实现
2.1思路
Spring 本来就提供了Cache的支持,最核心的就是实现Cache和CacheManager接口。但是Spring Cache存在以下问题:
- Spring Cache 仅支持单一的缓存来源,即:只能选择 Redis 实现或者 Caffeine 实现,并不能同时使用。
- 数据一致性:各层缓存之间的数据一致性问题,如应用层缓存和分布式缓存之前的数据一致性问题。
由此我们可以通过重新实现Cache和CacheManager接口,整合redis和caffeine,从而实现多级缓存。在讲实现原理之前先看看多级缓存调用逻辑图:
2.2实现
首先,我们需要一个多级缓存配置类,方便对缓存属性的动态配置,通过开关做到可插拔。
ini
复制代码
@ConfigurationProperties(prefix = "multilevel.cache") @Data public class MultilevelCacheProperties { /** * 一级本地缓存最大比例 */ private Double maxCapacityRate = 0.2; /** * 一级本地缓存与最大缓存初始化大小比例 */ private Double initRate = 0.5; /** * 消息主题 */ private String topic = "multilevel-cache-topic"; /** * 缓存名称 */ private String name = "multilevel-cache"; /** * 一级本地缓存名称 */ private String caffeineName = "multilevel-caffeine-cache"; /** * 二级缓存名称 */ private String redisName = "multilevel-redis-cache"; /** * 一级本地缓存过期时间 */ private Integer caffeineExpireTime = 300; /** * 二级缓存过期时间 */ private Integer redisExpireTime = 600; /** * 一级缓存开关 */