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; } //程序的结果是什么&…...

wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...

android RelativeLayout布局
<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...