Redis缓存技术详解与实战
Redis缓存技术详解与实战
Redis作为一个开源的内存数据结构存储系统,它可以用作数据库、缓存和消息代理。在现代高并发、大数据量处理的系统中,Redis作为缓存层的应用越来越广泛。本文将详细讲解Redis在查询、添加缓存、更新缓存、缓存预热、缓存穿透、缓存雪崩、缓存击穿等场景下的应用及解决方案,并通过实例代码来加深理解。
1. 查询缓存
1.1 场景描述
在Web应用中,对于读多写少的场景,为了提升性能,我们通常会选择将热点数据放入Redis中进行缓存。当应用需要读取数据时,首先会尝试从Redis中获取,如果Redis中存在该数据,则直接返回;否则,从数据库中查询并放入Redis中。
1.2 如何使用redis
在应用程序中,当需要获取某个数据项时,首先会尝试从Redis缓存中获取。如果缓存中存在该数据项,则直接返回给应用程序,从而避免了访问后端数据库的开销。如果缓存中不存在该数据项,则从数据库中获取数据,并将其存储在Redis缓存中以备后用。
1.3 解决方案
import redis.clients.jedis.Jedis; public class RedisCache { private static final String REDIS_HOST = "localhost"; private static final int REDIS_PORT = 6379; private static Jedis jedis; static { jedis = new Jedis(REDIS_HOST, REDIS_PORT); } public static String getData(String key) { String data = jedis.get(key); if (data == null) { // 模拟从数据库查询数据 data = "Data from DB"; // 将数据存入Redis缓存 jedis.set(key, data); // 可以设置过期时间 jedis.expire(key, 60); // 60秒后过期 } return data; }
}
2. 添加缓存
2.1 场景描述
当数据发生更新时,为了保证缓存与数据库的一致性,我们需要将数据同步更新到Redis中。
2.2 如何使用redis
当有新数据需要存储时,可以直接将数据添加到Redis缓存中。这通常发生在数据首次被创建或修改时。将数据存储在Redis中可以使后续的数据访问更加快速。
2.3 解决方案
// 实际上,在查询缓存的示例中,如果Redis中没有数据,就已经包含了添加缓存的逻辑
// 但为了明确说明,这里再提供一个简单的添加缓存方法
public static void addData(String key, String value) { jedis.set(key, value); // 可以选择性地设置过期时间 jedis.expire(key, 60); // 60秒后过期
}
3. 更新缓存
3.1 场景描述
在某些场景下,我们可能需要对缓存的数据进行批量更新或定期更新。
3.2 如何使用redis
当数据发生变化时,需要更新Redis缓存中的相应项以确保缓存中的数据是最新的。这可以通过简单地使用Redis的SET命令(或相应的库函数)来实现,用新的数据值替换旧的数据值。
3.3 解决方案
public static void updateData(String key, String newValue) { // 假设newValue是新的数据值 jedis.set(key, newValue); // 可以选择性地更新过期时间 jedis.expire(key, 60); // 如果需要的话
}
4. 缓存预热
4.1 场景描述
在系统启动或低峰时段,为了提升后续访问的性能,我们可以预先将热点数据加载到Redis缓存中。
4.2 如何使用redis
缓存预热是在系统启动或低峰时段预先加载缓存数据的过程。通过预先加载数据到缓存中,可以确保在高峰时段应用程序可以更快地响应请求,因为所需的数据已经在缓存中可用。缓存预热通常涉及从数据库中读取数据并将其存储在Redis缓存中。
4.3 解决方案
编写一个预热脚本,在系统启动或低峰时段,将预计会被频繁访问的数据加载到Redis中。
public static void warmUpCache() { // 假设我们有一个需要预热的key列表 List<String> keysToWarmUp = Arrays.asList("key1", "key2", "key3"); for (String key : keysToWarmUp) { // 模拟从数据库查询数据 String data = "Data for " + key; // 将数据添加到Redis缓存中 jedis.set(key, data); // 设置过期时间(如果需要) jedis.expire(key, 60 * 60 * 24); // 一天后过期 }
}
5. 缓存穿透
5.1 场景描述
缓存穿透是指查询一个不存在的数据,由于缓存中不存在该数据,导致每次请求都会去数据库中查询,从而失去缓存的意义。
5.2 如何使用redis
缓存穿透是指查询一个不存在的数据,由于缓存中不存在该数据,因此每次查询都会去数据库查询,从而增加了数据库的负载。为了解决这个问题,可以使用布隆过滤器来快速判断一个数据是否存在于Redis缓存中。如果布隆过滤器判断该数据不存在于缓存中,则可以直接返回结果,而无需去数据库查询。
5.3 解决方案
-
布隆过滤器
使用布隆过滤器来过滤掉不存在的数据,减少对数据库的无效查询。 -
空值缓存
对于不存在的数据,在Redis中缓存一个空值或特殊标记,并设置一个较短的过期时间。
由于Java本身不直接支持布隆过滤器,但可以使用Google的Guava库或者Redis的Bitmaps来实现类似的功能。这里仅提供一个概念性的描述。
6. 缓存雪崩
6.1 场景描述
缓存雪崩是指缓存中大量数据同时过期,导致大量请求直接涌入数据库,给数据库带来巨大压力。
6.2 如何使用redis
缓存雪崩是指由于大量的缓存数据同时过期,导致大量的请求都去数据库查询,从而增加了数据库的负载。为了解决这个问题,可以采取以下几种策略:
- 随机过期时间:为缓存数据设置不同的过期时间,以避免大量的缓存数据同时过期。
- 缓存降级:当缓存不可用或查询压力过大时,可以临时关闭缓存查询,直接返回默认数据或执行一些降级逻辑。
- 缓存预热:在系统启动或低峰时段预先加载缓存数据,以减轻高峰时段的压力。
6.3 解决方案
-
随机过期时间
设置缓存过期时间时,避免大量数据同时过期,可以为每个key设置一个随机的过期时间。 -
降级策略
当数据库压力过大时,可以暂时关闭部分非核心功能,保证核心功能的正常运行。
在Java中,防止缓存雪崩的策略主要是确保缓存的key不是同时过期。
// 当设置缓存过期时间时,使用随机时间
public static void setWithRandomExpire(String key, String value) { int randomSeconds = 60 + new Random().nextInt(60 * 60); // 1分钟到1小时之间的随机时间 jedis.setex(key, randomSeconds, value);
}
7. 缓存击穿
7.1 场景描述
缓存击穿是指某个热点key突然过期,此时大量请求会涌入数据库,导致数据库压力骤增。
7.2 如何使用redis
缓存击穿是指某个热点数据的缓存突然失效,导致大量的请求都去数据库查询该数据。为了解决这个问题,可以使用锁或其他同步机制来确保只有一个请求去数据库查询数据,而其他请求则等待第一个请求返回数据并更新缓存。这样,其他请求就可以直接从缓存中获取数据,而无需再去数据库查询。
7.3 解决方案
-
互斥锁
在访问缓存之前,使用互斥锁(如Redis的SETNX命令)来确保只有一个请求能够去数据库中查询数据,其他请求则等待该请求将数据加载到缓存中。 -
热点数据永不过期
对于某些热点数据,可以设置其永不过期,或者设置一个较长的过期时间。
import java.util.concurrent.locks.ReentrantLock; public class CacheWithLock { private static final ReentrantLock lock = new ReentrantLock(); public static String getDataWithLock(String key) { String data = jedis.get(key); if (data == null) { lock.lock(); try { // 再次检查,防止其他线程已经加载了数据 data = jedis.get(key); if (data == null) { // 模拟从数据库查询数据 data = "Data from DB with lock"; // 将数据存入Redis缓存 jedis.set(key, data); // 设置过期时间 jedis.expire(key, 60); } } finally { lock.unlock(); } } return data; }
}
相关文章:
Redis缓存技术详解与实战
Redis缓存技术详解与实战 Redis作为一个开源的内存数据结构存储系统,它可以用作数据库、缓存和消息代理。在现代高并发、大数据量处理的系统中,Redis作为缓存层的应用越来越广泛。本文将详细讲解Redis在查询、添加缓存、更新缓存、缓存预热、缓存穿透、…...
业务架构的位置及关系
背景 我们已经了解了业务架构的核心元素组成,以及各个扩展元素,同时对各个元素的关系协同也有了一些了解,那么接下来,我们进一步在宏观层面来看业务架构与其他架构的关系。 企业架构 企业架构有多种理解,也有多种叫…...
CMS与AI的融合:构建万能表单小程序系统
引言: 随着人工智能技术的飞速发展,MyCMS作为一款功能强大的内容管理系统,通过集成AI技术,进一步拓展了其应用范围和智能化水平。本文将探讨如何利用MyCMS结合AI技术,构建一个能够将用户提交的万能表单数据转化为智能提…...
机器学习常见知识点 2:决策树
文章目录 决策树算法1、决策树树状图2、选择最优决策条件3、决策树算法过程→白话决策树原理决策树构建的基本步骤常见的决策树算法决策树的优缺点 【五分钟机器学习】可视化的决策过程:决策树 Decision Tree 关键词记忆: 纯度、选择最优特征分裂、熵、基…...
海洋CMS admin_notify.php 远程代码执行漏洞复现(CVE-2024-30565)
0x01 产品简介 海洋CMS是一套专为不同需求的站长而设计的内容管理系统,灵活、方便、人性化设计、简单易用是最大的特色,可快速建立一个海量内容的专业网站。海洋CMS基于PHP+MySql技术开发,完全开源免费 、无任何加密代码。 0x02 漏洞概述 海洋CMS admin_notify.php 接口处…...
Spring、Spring MVC、MyBatis和Spring Boot对比
在对比Spring、Spring MVC、MyBatis和Spring Boot时,我们可以从以下几个方面进行详细的分析: Spring框架: 作用:Spring是一个轻量级的IoC(控制反转)和AOP(面向切面编程)容器&#…...
【Linux高级IO】select、poll、epoll
【Linux高级IO】select、poll、epoll toc 作者:爱写代码的刚子 时间:2024.6.5 前言:本篇博客将会介绍面试重点考察的select、poll、epoll IO: input && Output read && write 应用层read&&write的时候,…...
Etcd Raft架构设计和源码剖析2:数据流
Etcd Raft架构设计和源码剖析2:数据流 | Go语言充电站 前言 之前看到一幅描述etcd raft的流程图,感觉非常直观,但和自己看源码的又有些不同,所以自己模仿着画了一下,再介绍一下。 下图从左到右依次分为4个部分&…...
深入理解Qt多线程编程(QThreadPool)
多线程编程在现代软件开发中变得越来越重要,它能够提高应用程序的响应速度和处理性能。在Qt框架中,QThreadPool作为线程池管理工具,被频繁的使用。 目录 概述 接口介绍 底层原理解析 使用方法 概述 QThreadPool是Qt提供的一个线程池实现&a…...
Prisma数据库ORM框架学习
初始化项目 中文网站 点击快速开始,点击创建sql项目,后面一步一步往后走 这个博主也挺全的,推荐下 可以看这个页面初始化项目跟我下面是一样的,这里用得是ts,我下面是js,不需要额外的配置了 1.vscode打开一个空文件夹 2.npm init -y 初始化package.json 3.安装相关依赖 …...
Flutter-使用MethodChannel 实现与iOS交互
前言 使用 MethodChannel 在 Flutter 与原生 Android 和 iOS 之间进行通信,可以让你在 Flutter 应用中调用设备的原生功能。 基础概念 MethodChannel:Flutter 提供的通信机制,允许消息以方法调用的形式在 Flutter 与原生代码之间传递。方法…...
【星海随笔】云解决方案学习日志篇(一) ELK,kibana,Logstash安装
心路历程 本来想最近再研究研究DPDK的。但是自己做一个东西很多时候没有回报。因为自己的低学历问题,类似工作的面试都没有。所以很多东西学了很快就忘了,没有地方可以用。 今天看到了一个大佬,除了发型外,很多想法还是很共鸣的。 Shay Banon 决定开始跟…...
【leetcode】hot100 哈希表
1. 两数之和 1.1 题目 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。…...
每日5题Day22 - LeetCode 106 - 110
每一步向前都是向自己的梦想更近一步,坚持不懈,勇往直前! 第一题:106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode) class Solution {public TreeNode buildTree(int[] inorder, int[] postorder) {…...
【Python】读取文件夹中所有excel文件拼接成一个excel表格 的方法
我们平常会遇到下载了一些Excel文件放在一个文件夹下,而这些Excel文件的格式都一样,这时候需要批量这些文件合并成一个excel 文件里。 在Python中,我们可以使用pandas库来读取文件夹中的所有Excel文件,并将它们拼接成一个Excel表…...
7. 通配符和正则表达式
文章目录 7.1 通配符7.1.1 通配符介绍7.1.2 通配符示例 7.2 正则表达式7.2.1 grep命令7.2.2 基本正则表达式7.2.3 扩展正则表达式 7.1 通配符 在 Shell 中通配符用于查找文件名和目录名。它是由 Shell 处理的,只会出现在命令的参数中。 7.1.1 通配符介绍 * 匹…...
ROS2底层机制源码分析
init ->init_and_remove_ros_arguments ->init ->Context::init 保存初始化传入的信号 ->install_signal_handlers→SignalHandler::install 开线程响应信号 ->_remove_ros_arguments 移除ros参数 ->SingleNodeManager::instance().…...
超越 Transformer开启高效开放语言模型的新篇章
在人工智能快速发展的今天,对于高效且性能卓越的语言模型的追求,促使谷歌DeepMind团队开发出了RecurrentGemma这一突破性模型。这款新型模型在论文《RecurrentGemma:超越Transformers的高效开放语言模型》中得到了详细介绍,它通过…...
快速排序-Hoare 递归版 C语言
个人主页点这里~ 快速排序的简介: 快速排序是Hoare于1962年提出的一种 二叉树结构 的 交换 排序方法,其基本思想为:任取待排序元素序列中 的某元素作为 基准值 ,按照该排序码将待排序集合分割成 两子序列 , 左子序列中所有元素均 …...
C语言经典指针运算笔试题图文解析
指针运算常常出现在面试题中,画图解决是最好的办法。 题目1: #include <stdio.h> int main() {int a[5] { 1, 2, 3, 4, 5 };int* ptr (int*)(&a 1);printf("%d,%d", *(a 1), *(ptr - 1));return 0; } //程序的结果是什么&…...
SkillPilot:AI编程助手技能一键管理与安全部署实战
1. 项目概述与核心价值最近在折腾AI编程助手的时候,发现了一个挺有意思的痛点:虽然Claude Code、Cursor这些工具都支持通过SKILL.md文件来扩展功能,但每次想找个新技能,都得手动去GitHub上翻找、下载、配置,还得担心代…...
别再搞混了!改进DH与标准DH参数在IRB1200建模中的关键差异与选择
别再搞混了!改进DH与标准DH参数在IRB1200建模中的关键差异与选择 当你在为ABB IRB1200这类六轴工业机器人构建运动学模型时,是否曾被两种不同的DH参数表示法困扰?标准DH(Denavit-Hartenberg)和改进DH(Modif…...
OpenFOAM实战:在interFoam中植入多孔介质源项模拟复杂固壁
1. 多孔介质模拟的工程需求与原理 在流体力学仿真中,我们经常遇到需要处理复杂几何边界的情况。传统方法是通过精细的网格划分来精确描述固体边界,但这会带来两个主要问题:一是计算成本急剧上升,二是对于动态变化的边界࿰…...
小熊猫Dev-C++:5分钟搞定C++开发环境的终极解决方案 [特殊字符]
小熊猫Dev-C:5分钟搞定C开发环境的终极解决方案 🚀 【免费下载链接】Dev-CPP A greatly improved Dev-Cpp 项目地址: https://gitcode.com/gh_mirrors/dev/Dev-CPP 你是否曾为复杂的C开发环境配置而头疼?是否厌倦了臃肿的IDE占用大量系…...
ANSI转义序列封装:cursor-reset库实现终端光标精准控制
1. 项目概述与核心价值 最近在折腾一些自动化工具链,发现一个挺有意思的小项目,叫 zhitrend/cursor-reset 。乍一看名字,你可能会觉得这只是一个重置光标位置的小工具,但实际用下来,我发现它解决的痛点非常精准&…...
AI微服务治理新范式(Istio for AI技术栈深度拆解)
更多请点击: https://intelliparadigm.com 第一章:AI原生服务网格应用:2026奇点智能技术大会Istio for AI 在2026奇点智能技术大会上,Istio正式发布v1.22“Prometheus AI”版本,首次将LLM推理生命周期深度集成进数据平…...
告别驱动开发:手把手教你用himm工具在用户空间玩转Hi3516的GPIO
用户空间高效操控Hi3516 GPIO:himm工具实战指南 在嵌入式开发领域,传统的内核驱动开发往往需要经历漫长的编译、加载和调试周期。对于快速硬件验证和原型开发而言,这种开发模式显得过于笨重。海思Hi3516平台提供的himm工具,为开发…...
9 款 AI 写论文哪个好?2026 深度实测|虎贲等考 AI 凭真文献 + 真实图表 + 全流程实证,稳坐毕业论文首选
毕业季高频提问:9 款 AI 写论文哪个好?市面上工具看似大同小异,实则在文献真实性、实证图表、全流程覆盖、学术合规上差距巨大。通用大模型文献造假、普通工具无实证能力、小众平台功能残缺,选错轻则反复改稿,重则查重…...
从‘能用’到‘优雅’:Python函数设计的3个坏味道与5个重构技巧(附代码对比)
从‘能用’到‘优雅’:Python函数设计的3个坏味道与5个重构技巧(附代码对比) 在Python开发中,函数是最基本的代码组织单元。许多开发者能够快速实现功能,却往往忽视了函数设计的质量。本文将揭示三种典型的函数设计&qu…...
ATPG技术革新:从传统测试到单元感知与智能并行
1. 从“可靠的老黄牛”到“敏捷的赛马”:ATPG技术为何必须革新在芯片设计这个行当里干了十几年,Automatic Test Pattern Generation,也就是我们常说的ATPG,一直是个让人又爱又恨的角色。爱它,是因为它就像产线上那位最…...
