【Redis】多级缓存

【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,如果未命中则查询数据库。这种方式存在以下两个问题:

  1. 请求要经过 tomcat 处理,tomcat 的性能成为整个系统的瓶颈。
  2. redis缓存失效时,会对数据库产生冲击。

image-20230413203944261


2. 多级缓存方案

多级缓存就是充分利用请求处理的每个环节,分别添加缓存,减轻tomcat的压力,提升服务性能:

image-20230413204807451

注:用作缓存的nginx是业务nginx,需要部署为集群,再使用专门的nginx用来做反向代理


2.1 JVM进程缓存

image-20230413205008322

2.1.1 本地进程缓存

本地进程缓存:缓存在日常开发中起到了至关重要的作用,由于是存在在内存中,数据的读取速度非常快,能大量减少对数据库的访问,减少数据库的压力,我们把缓存分为两类:

  1. 分布式缓存,例如Redis:
    • 优点:存储容量大,可靠性更好,可以在集群间共享
    • 缺点:访问缓存有网络开销
    • 场景:缓存数据量较大、可靠性要求较高,需要在集群见共享
  2. 本地进程缓存,例如HashMap,GuavaCache:
    • 优点:读取本地内存,没有网络开销,速度更快
    • 缺点:存储容量有限,可靠性较低,无法共享
    • 场景:性能要求较高,缓存数据量较小

2.1.2 Caffeine

本地进程缓存Caffeine 是一个基于Java8开发的,提供了近乎最佳命中率的高性能的本地缓存库,目前spring内部的缓存使用的就算Caffeine。

引入依赖:

<dependency>
    <groupId>com.github.ben-manes.caffeinegroupId>
    <artifactId>caffeineartifactId>
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"));
}

运行结果如下:

image-20230413210838934


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服务器,它具有以下特点:

  1. 具备Nginx的完整功能
  2. 基于Lua语言进行扩展,集成了大量精良的Lua库、第三方模块
  3. 允许使用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

待续

你可能感兴趣的:(Redis,java,spring,redis)