Redis缓存问题详解和处理

news2024/11/26 14:56:11

缓存更新策略


在这里插入图片描述

缓存穿透


缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库.

  • 常见的解决方案:
    • 缓存空对象
      • 优点: 实现简单, 维护方便
      • 缺点: 额外的内存消耗, 可能造成短期的不一致
    • 布隆过滤
      • 优点: 内存占用较少(保存的是数据的二进制位)
      • 缺点: 实现复杂, 存在误判可能

在这里插入图片描述

  • 缓存空对象业务逻辑
    在这里插入图片描述
  • 写入空值
redisTemplate.opsForValue().set("item:1001", "", 30L, TimeUnit.SECONDS);

缓存雪崩


缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机, 导致大量请求到达数据库, 带来巨大压力.

解决方案:

  • 给不同的key的TTL添加随机值
  • 利用Redis集群提高服务的可用性
  • 给缓存业务添加降级限流策略
  • 给业务添加多级缓存

缓存击穿


缓存击穿问题也叫热点Key问题, 就是一个高并发访问并且缓存重建业务较复杂的key突然失效了, 无数的请求访问会瞬间给数据库带来巨大的冲击.

常见的解决方案:

  • 互斥锁
  • 逻辑过期

在这里插入图片描述

互斥锁

在这里插入图片描述

  • 定义获取锁和释放锁的方法
	private boolean tryLock(String key){
        Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, "1", 10L, TimeUnit.SECONDS);
        return BooleanUtils.isTrue(flag); 
    }
    private void unlock(String key){
        redisTemplate.delete(key);
    }

在这里插入图片描述
在这里插入图片描述

逻辑过期

在这里插入图片描述

  • 逻辑过期业务逻辑

在这里插入图片描述

  • 缓存预热

在这里插入图片描述

  • RedisData.java
@Data
public class RedisData {

    private LocalDateTime expireTime;

    private Object data;

}
  • 判断是否逻辑过期

在这里插入图片描述

  • 开启独立线程重建缓存

在这里插入图片描述

封装Redis工具类


import cn.hutool.core.util.BooleanUtil;
import cn.hutool.json.JSONUtil;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

@Component
public class CacheClient {

    private final StringRedisTemplate stringRedisTemplate;

    public CacheClient(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    public void set(String key, Object value, Long time, TimeUnit unit){
        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(value), time, unit);
    }

    public String get(String key){
        return stringRedisTemplate.opsForValue().get(key);
    }

    public void delete(String key){
        stringRedisTemplate.delete(key);
    }

    public void setWithLogicalExpire(String key, Object value, Long time, TimeUnit unit){
        // 设置逻辑过期
        RedisData redisData = new RedisData();
        redisData.setData(value);
        redisData.setExpireTime(LocalDateTime.now().plusSeconds(unit.toSeconds(time)));
        // 写入redis
        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(redisData));
    }

    /**
     * 获取锁
     */
    public boolean tryLock(String key){
        Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(key, "lock", 3L, TimeUnit.SECONDS);
        return BooleanUtil.isTrue(flag);
    }

    /**
     * 释放锁
     */
    public void unlock(String key){
        stringRedisTemplate.delete(key);
    }

    /**
     * 查询--缓存穿透处理
     */
    public <R, ID> R queryWithPassThrough(String keyPrefix, ID id, Class<R> type, Long time, TimeUnit unit, Function<ID, R> dbFallBack){
        String key = keyPrefix + id;
        String json = stringRedisTemplate.opsForValue().get(key);
        if(StringUtils.isNotBlank(json)){
            // 存在,直接返回
            return JSONUtil.toBean(json, type);
        }
        // 判断命中的是否为空值,缓存穿透处理会存""
        if(json != null){
            // 返回一个错误信息
            return null;
        }
        R r = dbFallBack.apply(id);
        if(r == null){
            // 将空值写入redis, 缓存穿透处理
            stringRedisTemplate.opsForValue().set(key, "", 2L, TimeUnit.SECONDS);
            return null;
        }
        // 存在, 写入redis
        this.set(key, JSONUtil.toJsonStr(r), time, unit);
        return r;
    }

}

@Data
class RedisData{
    // 逻辑过期时间
    private LocalDateTime expireTime;
    private Object data;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1511633.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【0基础学C语言】04-常量、变量

一、数据的存储 1.数据类型 首先来看看计算机是怎么存储数据的。总的来说,计算机中存储的数据可以分为两种:静态数据和动态数据。 1> 静态数据 概念:静态数据是指一些永久性的数据,一般存储在硬盘中。硬盘的存储空间一般都比较大,现在普通计算机的硬盘都有500G左右…

Leetcode每日一题[C++]-1261.在受污染的二叉树中查找元素

题目描述 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 给出一个满足下述规则的二叉树&#xff1a; root.val 0如果 treeNode.val x 且 treeNode.left ! null&#xff0c;那么 treeNode.left.val 2 * x 1如果 treeNode.val x 且 treeNode.right ! nu…

这些年背过的面试题——SpringMVC篇

1 什么是SpringMVC &#xff1f;简单介绍下你对SpringMVC的理解? SpringMVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架&#xff0c;通过把Model&#xff0c;View&#xff0c;Controller分离&#xff0c;将web层进行职责解耦&#xff0c;把复杂的web应用…

ST MotorControl Workbench 6.2.1 使用总结

目录 前言 软件安装 根据自己硬件配置参数 生成代码 开发板运行 ​ 总结 前言 好久没有玩ST的电机库了&#xff0c;已经更新到了MotorControl Workbench 6.2.1&#xff0c;6以上的版本比5的版本界面操作有很大的不同&#xff0c;核心算法有些增加。最近体验了一把使用自…

jeecg 启动 微服务 更改配置本地host地址

1. windows系统下&#xff0c;在开始—运行里面输入(找不到运行菜单可直接按WinR键)&#xff1a; C:\WINDOWS\system32\drivers\etc &#xff0c;如图所示&#xff1a; 2. 用记事本 打开这个文件 在最下面输入这个即可

G. Rudolf and Subway

解题思路 每条边的边权可选&#xff0c;由颜色决定同一颜色的线路可以直达颜色最多有种考虑将颜色视作链接点&#xff0c;进行分层图跑最短路最终结果除2最多建条边&#xff08;直接存状态Map跑最短路被毙掉了&#xff09; import java.io.*; import java.math.BigInteger; im…

【案例】IPC 中的WinCC RT Advanced PC项目,如何下载及开机自动启动?

导读&#xff1a;TIA WinCC Advanced (高级版)V17项目如何下载到目标计算机&#xff08;需要运行项目的电脑&#xff09;&#xff1f; 01WinCC RT Adv项目下载 1、在计算机开始菜单中点击“运行”或通过Win键R调出运行窗口&#xff0c;并输入 CMD 然后回车&#xff1a; 打开 W…

虚拟化

什么是虚拟化 虚拟化&#xff08;Virtualization&#xff09;是一种资源分配和管理技术&#xff0c;是将计算机的各种实体资源,比如CPU、内存、磁盘空间、网络适配器等&#xff0c;进行抽象转换后虚拟的设备,可以实现灵活地分割、组合为一个或多个计算机配置环境&#xff0c;并…

rt-thread组件之audio组件(结合mp3player包使用)

前言 继上一篇RT-Thread组件之Audio框架i2s驱动的编写的编写&#xff0c;应用层使用rt-thread软件包里面的wavplayer组件以及 rt-thread组件之audio组件(结合wavplayer包使用)的文章本篇使用的是 mp3player软件包&#xff0c;与wavplayer设计框架基本上是一样的&#xff0c;只…

万字完整版【C语言】指针详解~

一、前言 初始指针&#xff08;0&#xff09;&#xff1a;着重于讲解指针的概念、基本用法、注意事项、以及最后如何规范使用指针深入指针&#xff08;1&#xff09;&#xff1a;讲解指针变量常见的类型&#xff0c;如何去理解这些类型、最后就是如何正确的使用深入指针&#…

语音情感基座模型emotion2vec

在语音技术领域&#xff0c;准确理解用户的语音指令和意图是构建高效人机交互系统的基础。一个高品质的语音交互系统不仅需要理解字面上的语言内容&#xff0c;更应捕捉到说话者语音中蕴含的情感信息。这正是语音情感识别&#xff08;SER&#xff09;技术要解决的问题&#xff…

【libwebrtc】基于m114的构建

libwebrtc A C++ wrapper for binary release, mainly used for flutter-webrtc desktop (windows, linux, embedded).是 基于m114版本的webrtc 最新(20240309 ) 的是m122了。官方给出的构建过程 .gclient 文件 solutions = [{"name" : src,"url

Caffeine缓存

本地缓存基于本地环境的内存&#xff0c;访问速度非常快&#xff0c;对于一些变更频率低、实时性要求低的数据&#xff0c;可以放在本地缓存中&#xff0c;提升访问速度 使用本地缓存能够减少和Redis类的远程缓存间的数据交互&#xff0c;减少网络 I/O 开销&#xff0c;降低这…

Python 导入Excel三维坐标数据 生成三维曲面地形图(体) 5-1、线条平滑曲面且可通过面观察柱体变化(一)

环境和包: 环境 python:python-3.12.0-amd64包: matplotlib 3.8.2 pandas 2.1.4 openpyxl 3.1.2 scipy 1.12.0 代码: import pandas as pd import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from scipy.interpolate import griddata fro…

【软考中级】网络工程师:11.网络管理

11.1 网络管理五大功能域 故障管理、配置管理、计费管理、安全管理和性能管理。 故障管理&#xff1a;尽快发现故障&#xff0c;找出故障原因&#xff0c;以便找出补救措施。 配置管理&#xff1a;初始化、维护和关闭网络设备或子系统。 计费管理&#xff1a;计费监视主要是跟…

dubbo调用的自定义过滤器中设置MDC无法生效的问题

AI的解释 Dubbo自定义过滤器不生效可能有多种原因&#xff0c;以下是一些常见的原因及解决方法&#xff1a; 过滤器未正确配置&#xff1a; 检查过滤器是否已经在Dubbo的配置文件中正确声明&#xff0c;并且已经添加到过滤器链中。在XML配置中&#xff0c;应使用<dubbo:se…

Ubuntu 14.04:PaddleOCR基于PaddleServing的在线服务化部署(失败)

一、 二、安装 注&#xff1a; 安装 PaddleOCR 2.3 。 因为 PaddleOCR 2.4 的 推荐环境 PaddlePaddle > 2.1.2。 https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.4/doc/doc_ch/environment.md 安装前的环境准备 在使用Paddle Serving之前&#xff0c;需要完…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的常见车型识别系统(Python+PySide6界面+训练代码)

摘要&#xff1a;本文深入探讨了如何应用深度学习技术开发一个先进的常见车型识别系统。该系统核心采用最新的YOLOv8算法&#xff0c;并与早期的YOLOv7、YOLOv6、YOLOv5等版本进行性能比较&#xff0c;主要评估指标包括mAP和F1 Score等。详细解析了YOLOv8的工作机制&#xff0c…

【力扣白嫖日记】1321.餐馆营业额变化增长

前言 练习sql语句&#xff0c;所有题目来自于力扣&#xff08;https://leetcode.cn/problemset/database/&#xff09;的免费数据库练习题。 今日题目&#xff1a; 1321.餐馆营业额变化增长 表&#xff1a;Customer 列名类型cutomer_idintnamevarcharvisited_ondateamounti…

阻塞队列学习

1、什么是阻塞队列&#xff1f; 顾名思义&#xff0c;就是支持阻塞的队列&#xff0c;相比于其他的队列&#xff0c;阻塞队列支持以下特性&#xff1a; 队列为空的时候&#xff0c;获取元素的线程会等待队列变为非空。队列为满的时候&#xff0c;存储元素的线程会等待队列可以…