基于Java实现Redis多级缓存方案

 更新时间:2022年03月22日 17:20:27   作者:飞翔荷兰号  
这篇文章主要介绍了Redis多级缓存方案分享,传统缓存方案、多级缓存方案、JVM本地缓存,举例说明这些方案,具有一定的参考价值,需要的小伙伴可以参考一下

一、多级缓存

1. 传统缓存方案

请求到达tomcat后,先去redis中获取缓存,不命中则去mysql中获取

2. 多级缓存方案

  • tomcat的请求并发数,是远小于redis的,因此tomcat会成为瓶颈
  • 利用请求处理每个环节,分别添加缓存,减轻tomcat压力,提升服务性能

二、JVM本地缓存

缓存是存储在内存中,数据读取速度较快,能大量减少对数据库的访问,减少数据库压力

分布式缓存,如redis
 - 优点: 存储容量大,可靠性好,可以在集群中共享
 - 缺点: 访问缓存有网络开销
 - 场景: 缓存数据量大,可靠性高,需要在集群中共享的数据

进程本地缓存, 如HashMap, GuavaCache
- 优点:读取本地内存,没有网络开销,速度更快
- 缺点:存储容量有限,可靠性低(如重启后丢失),无法在集群中共享
- 场景:性能要求高,缓存数据量少

1. 实用案例

  • Caffeine是一个基于java8开发的,提供了近乎最佳命中率的高性能的本地缓存库
  • 目前spring内部的缓存用的就是这个
<dependency>
     <groupId>com.github.ben-manes.caffeine</groupId>
     <artifactId>caffeine</artifactId>
     <version>3.0.5</version>
 </dependency>
package com.erick.cache;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;

import java.time.Duration;

public final class CacheUtil {
    private static int expireSeconds = 2;
    public static Cache<String, String> cacheWithExpireSeconds;

    private static int maxPairs = 1;
    public static Cache<String, String> cacheWithMaxPairs;

    static {
        /*过期策略,写完60s后过期*/
        cacheWithExpireSeconds = Caffeine.newBuilder()
                .expireAfterWrite(Duration.ofSeconds(expireSeconds))
                .build();

        /*过期策略,达到最大值后删除
         * 1. 并不会立即删除,等一会儿才会删除
         * 2. 会将之前存储的数据删除掉*/
        cacheWithMaxPairs = Caffeine.newBuilder()
                .maximumSize(maxPairs)
                .build();
    }

    /*从缓存中获取数据
     * 1. 如果缓存中有,则直接从缓存中返回
     * 2. 如果缓存中没有,则去数据查询并返回结果*/
    public static String getKeyWithExpire(String key) {
        return cacheWithExpireSeconds.get(key, value -> {
            return getResultFromDB();
        });
    }

    public static String getKeyWithMaxPair(String key) {
        return cacheWithMaxPairs.get(key, value -> {
            return getResultFromDB();
        });
    }

    private static String getResultFromDB() {
        System.out.println("数据库查询");
        return "db result";
    }
}
package com.erick.cache;

import java.util.concurrent.TimeUnit;

public class Test {

    @org.junit.Test
    public void test01() throws InterruptedException {
        CacheUtil.cacheWithExpireSeconds.put("name", "erick");
        System.out.println(CacheUtil.getKeyWithExpire("name"));
        TimeUnit.SECONDS.sleep(3);
        System.out.println(CacheUtil.getKeyWithExpire("name"));
    }

    @org.junit.Test
    public void test02() throws InterruptedException {
        CacheUtil.cacheWithMaxPairs.put("name", "erick");
        CacheUtil.cacheWithMaxPairs.put("age", "12");

        System.out.println(CacheUtil.getKeyWithMaxPair("name"));
        System.out.println(CacheUtil.getKeyWithMaxPair("age"));

        TimeUnit.SECONDS.sleep(2);

        System.out.println(CacheUtil.getKeyWithMaxPair("name")); // 查询不到了
        System.out.println(CacheUtil.getKeyWithMaxPair("age"));
    }
}

三、缓存一致性

1. 常见方案

1.1 设置有效期

  • 给缓存设置有效期,到期后自动删除。再次查询时可以更新
  • 优势:简单,方便
  • 缺点:时效性差,缓存过期之前可能不一致
  • 场景:更新频率低,时效性要求比较低的业务

1.2 同步双写

  • 在修改数据库的同时,直接修改缓存
  • 优势:有代码侵入,缓存与数据库强一致性
  • 缺点:代码进入,耦合性高
  • 场景:对一致性,失效性要求较高的缓存数据

1.3 异步通知

  • 修改数据库时发送事件通知,相关服务监听到后修改缓存数据
  • 优势:低耦合,可以同时通知多个缓存服务
  • 缺点:时效性一把,可能存在缓存不一致问题
  • 场景:时效性一般,有多个服务需要同步

2. 基于Canal的异步通知

  • 是阿里旗下的一款开源项目,基于java开发
  • 基于数据库增量日志解析,提供增量数据订阅和消费
  • 基于mysql的主从备份的思想

2.1 mysql主从复制

2.2 canal 工作原理

  • canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议
  • MySQL master 收到 dump 请求, 开始推送 binary log 给 slave (即 canal )
  • canal 解析 binary log 对象(原始为 byte 流)

到此这篇关于Redis多级缓存方案分享的文章就介绍到这了,更多相关Redis多级缓存内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java搭建简单Netty开发环境入门教程

    Java搭建简单Netty开发环境入门教程

    这篇文章主要介绍了Java搭建简单Netty开发环境入门教程,有详细的代码展示和maven依赖,能够帮助你快速上手Netty开发框架,需要的朋友可以参考下
    2021-06-06
  • java字节码框架ASM操作字节码的方法浅析

    java字节码框架ASM操作字节码的方法浅析

    这篇文章主要给大家介绍了关于java字节码框架ASM如何操作字节码的相关资料,文中通过示例代码介绍的很详细,有需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-01-01
  • SpringBoot利用自定义json序列化器实现敏感字段数据脱敏详解

    SpringBoot利用自定义json序列化器实现敏感字段数据脱敏详解

    这篇文章主要介绍了SpringBoot利用自定义json序列化器实现敏感字段数据脱敏详解,因为案例代码用到了hutool提供的DesensitizedUtil数据脱敏工具类,这里要引入hutool的依赖,如果你需要自定义 数据脱敏的逻辑,可以不引入这个依赖,需要的朋友可以参考下
    2024-01-01
  • Java方法重载和重写原理区别解析

    Java方法重载和重写原理区别解析

    这篇文章主要介绍了Java方法重载和重写原理区别解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • Java开发神器Lombok安装与使用详解

    Java开发神器Lombok安装与使用详解

    Lombok的安装分两部分:Idea插件的安装和maven中pom文件的导入,本文重点给大家介绍Java开发神器Lombok安装与使用详解,感兴趣的朋友跟随小编一起看看吧
    2022-02-02
  • spring中前端明明传了值后端却接收不到问题解决办法

    spring中前端明明传了值后端却接收不到问题解决办法

    在学习Spring的时候遇到了一个问题,后台一直接收不到前台传递过来的参数,耽误了好长时间终于找到了原因,这篇文章主要给大家介绍了关于spring中前端明明传了值后端却接收不到问题的解决办法,需要的朋友可以参考下
    2024-05-05
  • 详解JAVA 连等赋值问题

    详解JAVA 连等赋值问题

    这篇文章主要介绍了JAVA 连等赋值问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • java连接Mongodb实现增删改查

    java连接Mongodb实现增删改查

    这篇文章主要为大家详细介绍了java连接Mongodb实现增删改查,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • SpringBoot+redis配置及测试的方法

    SpringBoot+redis配置及测试的方法

    这篇文章主要介绍了SpringBoot+redis配置及测试的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • 详解通过maven运行项目的两种方式

    详解通过maven运行项目的两种方式

    这篇文章主要介绍了通过maven运行项目的两种方式,给大家提到了通过tomcat的方式来启动maven项目的方法,通过图文并茂的形式给大家介绍的非常详细,需要的朋友可以参考下
    2021-12-12

最新评论