【Redis】多级缓存
文章目录
- 【Redis】多级缓存
- 1. 传统缓存的问题
- 2. 多级缓存方案
- 2.1 JVM进程缓存
- 2.1.1 本地进程缓存
- 2.1.2 Caffeine
- 2.2 Nginx缓存
- 2.2.1 准备工作
- 2.2.2
1. 传统缓存的问题
传统的缓存策略一般是请求到达 tomcat
后,先查询redis,如果未命中则查询数据库。这种方式存在以下两个问题:
- 请求要经过
tomcat
处理,tomcat
的性能成为整个系统的瓶颈。 - redis缓存失效时,会对数据库产生冲击。
2. 多级缓存方案
多级缓存就是充分利用请求处理的每个环节,分别添加缓存,减轻tomcat的压力,提升服务性能:
注:用作缓存的nginx是业务nginx,需要部署为集群,再使用专门的nginx用来做反向代理
2.1 JVM进程缓存
2.1.1 本地进程缓存
本地进程缓存:缓存在日常开发中起到了至关重要的作用,由于是存在在内存中,数据的读取速度非常快,能大量减少对数据库的访问,减少数据库的压力,我们把缓存分为两类:
- 分布式缓存,例如Redis:
- 优点:存储容量大,可靠性更好,可以在集群间共享
- 缺点:访问缓存有网络开销
- 场景:缓存数据量较大、可靠性要求较高,需要在集群见共享
- 本地进程缓存,例如HashMap,GuavaCache:
- 优点:读取本地内存,没有网络开销,速度更快
- 缺点:存储容量有限,可靠性较低,无法共享
- 场景:性能要求较高,缓存数据量较小
2.1.2 Caffeine
本地进程缓存:Caffeine
是一个基于Java8开发的,提供了近乎最佳命中率的高性能的本地缓存库,目前spring内部的缓存使用的就算Caffeine。
引入依赖:
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
示例:
@Test
void testBasicOps() {
//构建cache对象
Cache<String, String> cache = Caffeine.newBuilder().build();
//存数据
cache.put("gf", "刘亦菲");
//取数据
String gf = cache.getIfPresent("gf");
System.out.println("gf = " + gf);
//取数据,如果未命中,则查询数据库
//参数1:缓存的key
//参数2:lambda表达式,表达式的参数就是缓存的key,方法体就是查询逻辑
//优先根据key查询jvm缓存,如果未命中,则执行参数2的lambda表达式
String defaultGF = cache.get("defaultGF", key -> {
//根据key去数据库查询数据
return "王祖贤";
});
System.out.println("defaultGF = " + defaultGF);
System.out.println("defaultGF = " + cache.getIfPresent("defaultGF"));
}
运行结果如下:
Caffeine
提供了三种缓存驱逐策略:
-
基于容量:设置缓存的数量上限
Cache<String, String> cache = Caffeine.newBuilder() .maximumSize(10_000)//上限为10000个key .build();
-
基于时间:设置缓存的有效时间
// 创建缓存对象 Cache<String, String> cache = Caffeine.newBuilder() .expireAfterWrite(Duration.ofSeconds(10)) // 设置缓存有效期为 10 秒,从最后一次写入开始计时 .build();
-
基于引用:设置缓存为软引用或弱引用,利用GC来回收缓存数据。性能较差,不建议使用。
在默认的情况下,当一个缓存元素过期的时候,Caffeine
不会自动立即将其清理和驱逐,而是在一次读或写操作后,或者在空闲时间完成对失效数据的驱逐。
2.2 Nginx缓存
2.2.1 准备工作
首先需要安装 OpenResty
,它本质上也是一个nginx服务器,它具有以下特点:
- 具备Nginx的完整功能
- 基于Lua语言进行扩展,集成了大量精良的Lua库、第三方模块
- 允许使用Lua自定义业务逻辑、自定义库
安装好 OpenResty
后,安装目录为 /usr/local/openresty
。
在 /usr/local/openresty/nginx/conf
目录下的nginx.conf文件添加如下模块:
# 加载lua 模块
lua_package_path "/usr/local/openresty/lualib/?.lua;;";
# 加载c模块
lua_package_cpath "/usr/local/openresty/lualib/?.so;;";
对 /api/item
这个路径进行监听:
location /api/item {
# 响应类型,这里返回json
default_type application/json;
# 响应数据由 lua/item.lua这个文件来决定
content_by_lua_file lua/item.lua;
}
注:lua/item.lua的lua目录和nginx同级,完整路径为/usr/local/openresty/lua,在这个文件下面就可以编写缓存脚本。
2.2.2
待续