Redis-缓存击穿-逻辑过期

Redis-缓存击穿-逻辑过期实现

缓存击穿:也称热点key问题,大量访问一个key,而这个key恰巧到期了,导致大量的请求访问数据库。增大数据库的负担。为了解决这个问题可以采用互斥锁或逻辑过期的方式解决。本章采用逻辑过期的方式解决此问题。

流程图:

第一点需要进行缓存预热,把经常用的key预先缓存到redis中

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    /** 缓存数据KEY */
    private final String CACHE_SHOP_KEY = "CACHE_SHOP_KEY:";
    /** 缓存互斥锁KEY */
    private final String CACHE_SHOP_LOCK_KEY = "CACHE_SHOP_LOCK_KEY:";

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private static final ExecutorService CACHE_REBUILD_EXECUTOR = Executors.newFixedThreadPool(10);





/**
     * redis缓存
     * 缓存击穿
     */
    @Override
    public BooksVo selectById(Long bookId) {
        // 缓存击穿-互斥锁
        // return tryCacheMutex(bookId);

        // 缓存击穿-逻辑过期时间
        return tryCacheMutex2(bookId);
    }



/**
     * redis缓存
     * 缓存击穿-逻辑过期版本
     * @param bookId
     */
    private BooksVo tryCacheMutex2(Long bookId) {
        // RedisKey
        String cacheKey = CACHE_SHOP_KEY + bookId;
        // 1.从Redis查询商铺缓存
        // 获取缓存数据
        String contentBook = stringRedisTemplate.opsForValue().get(cacheKey);
        // 2.判断缓存是否命中
        if (StringUtils.isBlank(contentBook)){
            // 3.1缓存未命中 直接返回结果
            return null;
        }

       // 3.2缓存命中-获取数据
        RedisData redisData = JSONUtil.toBean(contentBook, RedisData.class);
        BooksVo booksVo = JSONUtil.toBean((JSONObject) redisData.getData(), BooksVo.class);
        LocalDateTime expireSecond = redisData.getExpireSecond();
        //  4.缓存未过期 直接返回数据
        if (expireSecond.isAfter(LocalDateTime.now())){
            return booksVo;
        }
        // 5.缓存过期-获取互斥锁
        if (tryLock(bookId)){
            // check double
            String s = stringRedisTemplate.opsForValue().get(cacheKey);
            RedisData redisData1 = JSONUtil.toBean(s, RedisData.class);
            if (BooleanUtil.isFalse(redisData1.getExpireSecond().isAfter(LocalDateTime.now()))){
                // 获取互斥锁成功,开启独立线程,缓存重建
                CACHE_REBUILD_EXECUTOR.submit(() -> {
                    try {
                        // 重建缓存
                        saveCacheBook(bookId, 20L);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    } finally {
                        // 释放互斥锁
                        stringRedisTemplate.delete(CACHE_SHOP_LOCK_KEY + bookId);
                    }
                });
            }
        }
        // 返回已过期的数据
        return booksVo;
    }
                
                
                
     /**
     * 保存缓存信息
     */
    public void saveCacheBook(Long bookId, Long expireSeconds){
        // 1.查询数据库数据
        BooksVo booksVo = this.queryById(bookId);
        // 2.封装逻辑过期时间
        RedisData redisData = new RedisData();
        redisData.setData(booksVo);
        // 获取当前的时间 + 指定秒数
        redisData.setExpireSecond(LocalDateTime.now().plusSeconds(expireSeconds));
        // 3.写入redis
        stringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY + bookId, JSONUtil.toJsonStr(redisData));
    }

redisData实体类

@Data
public class RedisData {
    /** 逻辑过期时间 */
    private LocalDateTime expireSecond;

    /** 拓展实体类 */
    private Object data;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Golang笔记(下)

Golang学习笔记(下) 前篇:Golang学习笔记(上) 十四、错误处理 14.1使用error类型 func New(text string) error例子: package mainimport ("errors" // 导入errors包"fmt" )func main() {var number, divi…

【数据结构】树与二叉树遍历算法的应用(求叶子节点个数、求树高、复制二叉树、创建二叉树、二叉树存放表达式、交换二叉树每个结点的左右孩子)

目录 求叶子节点个数、求树高、复制二叉树、创建二叉树、二叉树存放表达式、交换二叉树每个结点的左右孩子应用一:统计二叉树中叶子结点个数的算法写法一:使用静态变量写法二:传入 count 作为参数写法三:不使用额外变量 应用二&am…

【Linux】socket编程2

欢迎来到Cefler的博客😁 🕌博客主页:折纸花满衣 🏠个人专栏:题目解析 目录 👉🏻客户端代码Makefile(生成目标文件)UdpClient.cc(客户端代码)服务端代码部分优化1(接受客户端时显示客…

基于51单片机低中高音7键电子琴音乐播放器

基于51单片机电子琴音乐播放器 (仿真+程序+原理图+PCB+设计报告) 功能介绍 具体功能: 1.可以使用按键切换音乐播放模式和弹奏模式; 2.LED灯显示在使用哪种模式; 3.音乐…

Redis部署之主从

使用两台云服务器,在 Docker 下部署。 Redis版本为:7.2.4 下载并配置redis 配置文件 下载 wget -c http://download.redis.io/redis-stable/redis.conf配置 master节点配置 bind 0.0.0.0 # 使得Redis服务器可以跨网络访问,生产环境请考虑…

第十四届蓝桥杯C/C++大学B组题解(二)

6、岛屿个数 #include <bits/stdc.h> using namespace std; const int M51; int T,m,n; int vis[M][M],used[M][M]; int dx[]{1,-1,0,0,1,1,-1,-1}; int dy[]{0,0,1,-1,1,-1,1,-1}; string mp[M]; struct node{//记录一点坐标 int x,y; }; void bfs_col(int x,int y){ qu…

C++ | Leetcode C++题解之第14题最长公共前缀

题目&#xff1a; 题解&#xff1a; class Solution { public:string longestCommonPrefix(vector<string>& strs) {if (!strs.size()) {return "";}int minLength min_element(strs.begin(), strs.end(), [](const string& s, const string& t)…

同步压缩理论

参考 在频率方向进行能量重新分配&#xff08;分配到中心&#xff09; 时频重排

实验4 DHCP基础配置

实验4 DHCP基础配置 一、 原理描述二、 实验目的三、 实验内容四、 实验配置五、 实验步骤1.基本配置2.配置DHCPServer功能3.配置DHCP Client 一、 原理描述 动态主机配置协议 DHCP是一个局域网的网络协议&#xff0c;使用UDP协议工作&#xff0c;主要有两个用途&#xff1a;用…

大话设计模式——16.命令模式(Command Pattern)

简介 请求以命令的形式包裹在对象中&#xff0c;并传给调用对象。调用对象寻找可以处理该命令的对象进行执行。命令模式是一种特殊的策略模式&#xff0c;体现多个策略执行的问题&#xff0c;而不是选择的问题 UML图 应用场景 界面选择、键盘、按钮、事件操作都类似命令模式 …

前端工程化理解 (2024 面试题)

最好介绍远古世界最好随性一点&#xff0c;不要太刻板 &#xff0c;不然像背书 什么是前端工程化&#xff1f; - 知乎 前端工程化的历史 互联网初期&#xff0c;09 年以前&#xff0c;页面只需要展示一些列表、表格、文章内容以及简单图片即可&#xff0c;其目的是为了传送信…

身份证正面打印、反面打印与打印在同一页

1 打印身份证正面 将身份证正面朝下放置&#xff0c;按打印机键盘上的数字【3】&#xff0c;再按【Start】键&#xff0c;选择A4大小打印&#xff0c;如图(1)所示&#xff1a; 图(1) A4纸复印 2 打印身份证反面 将身份证反面朝下放置&#xff0c;按打印机键盘上的数字【3】&…

KVM 高级功能部署

目录 一、案例分析 1.1、案例概述 1.2、案例前置知识点 1&#xff09;KVM 虚拟机迁移 2&#xff09;KSM 内核同页合并 1.3、案例环境 1&#xff09;本案例环境 2&#xff09;案例需求 3&#xff09;案例实现思路 二、案例实施 2.1、静态迁移 1&#xff09;在…

springboot+vue药店药品进销存采购管理系统0z10z

本系统采用intellij idea支持eclipse 项目架构&#xff1a;B/S架构web 开发语言&#xff1a;java 前端技术&#xff1a;vue.jsElementUi 后端框架&#xff1a;django、mybatis、Springmvc 运行环境&#xff1a;win10/win11、jdk1.8 可行性论证 社会可行性 开发本系统&#xff…

XC6206稳压芯片

mark 662k XC6206 的基本特性。这是一个 SOT23封装的 3.3V 稳压器。它输出最大工作电流为 100mA 最大特点便宜 参考链接 XC6206稳压芯片 (qq.com)https://mp.weixin.qq.com/s?__bizMzA5NjQyNjc2NQ&mid2452268489&idx1&sn90e920c596e3c2a382f81929c6313977&c…

Linux--进程的概念(一)

目录 一、冯诺依曼体系结构二、操作系统2.1 什么是操作系统2.2 操作系统的意义 三、进程3.1 进程的基本概念3.2 描述进程——PCB3.3 进程和程序的区别3.4 task_struct-PCB的一种3.5 task_struct的内容分类 四、如何查看进程4.1 通过系统文件查看进程4.2 通过ps指令查看进程 五、…

《公安机关互联网安全监督检查规定》系列之“解决方案”

随着中国互联网和信息网络飞速发展&#xff0c;无线网络普及到国内各个家庭和公共场所&#xff0c;成为人们日常办公和生活娱乐不可或缺的一部分。无线网络在创造商业价值、带来工作和生活便捷的同时&#xff0c;也同样让犯罪份子有了可乘之机&#xff0c;越来越多的网络违法活…

如何通过数据验证防止 Web API 攻击 - Web API 安全指南

充分的数据保护和用户保密是网页开发者的主要责任。因此&#xff0c;在构建 API 终端时&#xff0c;确保最高可能的安全性至关重要。 应用程序安全是客户端和服务器开发者共同的责任&#xff0c;一方的疏忽可能会造成灾难性后果。统计数据显示&#xff0c;2023 年的数据泄露导…

windows安装Redis,Mongo,ES并快速基本掌握开发流程

前言 这里只是一些安装后的基础操作&#xff0c;后期会学习更加深入的操作 基础操作 前言RedisRedis启动idea集成Redisjedis技术 Mongodbwindows版Mongodb的安装idea整合Mongodb ES(Elasticsearch)ESwindows下载ES文档操作idea整合ES低级别ES整合高级别ES整合 Redis Redis是…

HarmonyOS 开发-Grid和List内拖拽交换子组件位置

介绍 本示例分别通过onItemDrop()和onDrop()回调&#xff0c;实现子组件在Grid和List中的子组件位置交换。 效果图预览 使用说明&#xff1a; 拖拽Grid中子组件&#xff0c;到目标Grid子组件位置&#xff0c;进行两者位置互换。拖拽List中子组件&#xff0c;到目标List子组件…