如何使用 Redis 作为高效缓存

如何使用 Redis 作为高效缓存

Redis(Remote Dictionary Server)是一个高性能的 内存存储系统,通常被用作 缓存 来加速数据访问,提高应用的吞吐量和响应速度。本文详细讲解如何使用 Redis 作为高效缓存,包括基本原理、常见模式、最佳实践以及优化技巧。


1. 为什么使用 Redis 作为缓存?

相比于传统的数据库,Redis 具有以下优点:

  • 低延迟 & 高吞吐:Redis 基于内存操作,读写速度远超磁盘存储数据库。
  • 支持多种数据结构:支持 StringHashListSetSorted Set 等丰富的数据类型,适合不同的缓存场景。
  • 持久化支持:可选择性地使用 AOF 和 RDB 进行数据持久化,防止数据丢失。
  • 分布式支持:支持主从复制、哨兵模式和集群模式,能够横向扩展。
  • 丰富的过期策略:支持多种缓存淘汰策略,避免缓存占用过多内存。

2. Redis 缓存的常见使用模式

Redis 作为缓存一般采用 前置缓存(Look-aside Cache)写穿透缓存(Write-through Cache) 模式。

2.1. 前置缓存(Look-aside Cache)

原理:

  1. 先查询 Redis 缓存,如果命中则直接返回;
  2. 如果未命中(Cache Miss),则查询数据库,并将结果写入 Redis 缓存,便于后续访问。

代码示例(使用 Python + Redis):

import redis
import time# 连接 Redis
cache = redis.Redis(host='localhost', port=6379, decode_responses=True)def get_data_from_db(key):""" 模拟数据库查询 """time.sleep(1)  # 模拟查询延迟return f"Value of {key}"def get_data(key):""" 先查 Redis,未命中则查数据库,并存入 Redis """value = cache.get(key)if value is None:print("Cache Miss, Fetching from DB...")value = get_data_from_db(key)cache.setex(key, 3600, value)  # 设置 1 小时过期else:print("Cache Hit!")return value# 测试
print(get_data("user:1001"))
print(get_data("user:1001"))

优点:

  • 适用于 读多写少 的场景,如热点数据查询。
  • 缓存有效期 可控制,避免长期存储过期数据。

缺点:

  • 可能会遇到 缓存穿透缓存击穿缓存雪崩 等问题(后面会详细讲解)。

2.2. 写穿透缓存(Write-through Cache)

原理:

  1. 写数据时,同时更新数据库和 Redis,保证数据一致性;
  2. 读取数据时,先查 Redis,命中直接返回,未命中则从数据库查询,并更新缓存。

代码示例:

def update_data(key, value):""" 更新数据库,同时更新缓存 """print("Updating database...")# 这里模拟更新数据库time.sleep(1)  # 模拟写入延迟cache.setex(key, 3600, value)  # 立即更新缓存print("Cache updated!")# 测试
update_data("user:1001", "Updated Value")
print(get_data("user:1001"))  # 应该返回新的值

优点:

  • 适用于 读写频率相近 的场景,比如电商库存、用户账户余额。
  • 由于写时更新缓存,能够 减少缓存击穿问题

缺点:

  • 每次写操作都要更新缓存,可能会导致 写压力增加

3. 解决缓存常见问题

3.1. 缓存穿透

问题:

  • 用户请求的数据在数据库中 不存在,导致每次请求都 无法命中缓存,直接查询数据库。
  • 可能导致数据库 压力剧增,甚至崩溃。

解决方案:

  1. 缓存空值:对于查询结果为空的 key,也存入 Redis,避免频繁查询数据库:

    value = cache.get("user:9999")
    if value is None:db_value = get_data_from_db("user:9999")if db_value is None:cache.setex("user:9999", 3600, "NULL")  # 存一个空值else:cache.setex("user:9999", 3600, db_value)
    
  2. 布隆过滤器(Bloom Filter):在请求 Redis 之前,先用布隆过滤器判断 key 是否可能存在。


3.2. 缓存击穿

问题:

  • 某个热点 key 过期 后,大量并发请求同时查询数据库,造成数据库压力过大。

解决方案:

  1. 设置合理的过期时间,采用 随机过期时间 避免多个 key 同时过期。

  2. 互斥锁:在缓存失效后,只有 一个线程更新缓存,其他线程等待:

    lock = cache.setnx("lock:user:1001", 1)  # 尝试加锁
    if lock:value = get_data_from_db("user:1001")cache.setex("user:1001", 3600, value)  # 更新缓存cache.delete("lock:user:1001")  # 释放锁
    

3.3. 缓存雪崩

问题:

  • 大量缓存 key 同时过期,导致大量请求直接访问数据库,造成宕机风险。

解决方案:

  1. 给缓存 key 设定不同的过期时间(如 3600 + random(600) 秒)。
  2. 使用 Redis 集群,分散缓存压力。
  3. 预加载数据,定期更新缓存,避免大规模过期。

4. Redis 高级优化技巧

4.1. 使用合适的数据结构

  • 字符串(String):适用于简单的 key-value 存储,如用户信息缓存。
  • 哈希(Hash):适用于存储结构化数据。
  • 列表(List):适用于消息队列。
  • 集合(Set):适用于去重操作。
  • 有序集合(Sorted Set):适用于排行榜。

4.2. Redis LRU 淘汰策略

CONFIG SET maxmemory-policy allkeys-lru

4.3. 采用 Redis 分布式架构

  • 主从复制:适用于读多写少的场景。
  • Redis 哨兵:提供自动故障恢复。
  • Redis Cluster:支持 分片存储

总结

Redis 作为高效缓存,能够极大提高数据访问速度,降低数据库压力。但在实际使用中,需要结合缓存策略、淘汰策略和分布式架构,避免缓存穿透、击穿和雪崩等问题,实现高可用、高性能的缓存系统。

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

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

相关文章

AUTOSAR从入门到精通-自动驾驶测试技术

目录 前言 算法原理 测试场景定义与作用 测试场景要素 测试场景分类 场景信息提取与挖掘方法 自动驾驶感知测试分类 自动驾驶图像系统测试 自动驾驶激光雷达系统测试 自动驾驶融合感知系统测试 自动驾驶仿真测试 1. 功能安全 2. 预期功能安全 3. 软件测试 4.敏捷…

Bootstrap 下拉菜单

Bootstrap 下拉菜单 Bootstrap 是一个流行的前端框架,它提供了许多预构建的组件,其中之一就是下拉菜单。下拉菜单是一个交互式元素,允许用户从一系列选项中选择一个。在本篇文章中,我们将详细介绍如何在 Bootstrap 中创建和使用下…

蓝桥杯备考:堆和priority queue(优先级队列)

堆的定义 heap堆是一种特殊的完全二叉树,对于树中的每个结点,如果该结点的权值大于等于孩子结点的权值,就称它为大根堆,小于等于就叫小根堆,如果是大根堆,每个子树也是符合大根堆的特征的,如果是…

到底应不应该使用@Builder

大多数同学使用 Builder 无非就是为了链式编程,然而 Builder 并不是链式编程的最佳实践,它会额外创建内部类,存在继承关系时还需要使用 SuperBuilder 注解,设置默认值时也需要额外的 Builder.Default 去设置默认值,无疑…

微软官方Windows 10系统ISO镜像文件下载指南

简介 什么是ISO镜像文件 ISO镜像文件是一种特殊的数字文件格式, 精确复制了物理光盘的所有内容和结构 。这种文件通常用于存储完整的操作系统安装程序或其他大型软件包,便于在网络上传输和长期保存。ISO文件的核心优势在于其高度的完整性和可靠性&…

RabbitMQ-消息可靠性以及延迟消息

目录 消息丢失 一、发送者的可靠性 1.1 生产者重试机制 1.2 生产者确认机制 1.3 实现生产者确认 (1)开启生产者确认 (2)定义ReturnCallback (3)定义ConfirmCallback 二、MQ的持久化 2.1 数据持久…

fgets、scanf存字符串应用

题目1 夺旗(英语:Capture the flag,简称 CTF)在计算机安全中是一种活动,当中会将“旗子”秘密地埋藏于有目的的易受攻击的程序或网站。参赛者从其他参赛者或主办方偷去旗子。 非常崇拜探姬的小学妹最近迷上了 CTF&am…

【C语言系列】深入理解指针(1)

前言 总所周知,C语言中指针部分是非常重要的,这一件我们会介绍指针相关的内容,当然后续我还会出大概4篇与指针相关的文章,来深入的讲解C语言指针部分,希望能够帮助到指针部分薄弱或者根本不会的程序员们,后…

力扣面试150 串联所有单词的子串 分组滑动窗口

Problem: 30. 串联所有单词的子串 参考题解 滑动窗口 class Solution {public List<Integer> findSubstring(String s, String[] words) {int n s.length(), m words.length, w words[0].length();// 统计 words 中「每个目标单词」的出现次数Map<String, Integ…

CSS笔记01

黑马程序员视频地址&#xff1a; 前端Web开发HTML5CSS3移动web视频教程https://www.bilibili.com/video/BV1kM4y127Li?vd_source0a2d366696f87e241adc64419bf12cab&spm_id_from333.788.videopod.episodes 目录 引入方式 CSS特性 继承性 层叠性 优先级 Emmet写法 …

django应急物资管理系统

Django应急物资管理系统是一种高效、智能的管理系统&#xff0c;旨在应对自然灾害、事故灾难等突发事件&#xff0c;确保救援物资能够及时、准确地调配到需要的地方。 一、系统背景与意义 在现代社会&#xff0c;各类突发事件频繁发生&#xff0c;对人民生命财产安全构成严重…

管理口令安全和资源(二)

DBMS_METADATA DBMS_METADATA 是 Oracle 数据库中的一个包&#xff0c;它提供了用于管理数据库元数据的工具和过程。元数据是关于数据的数据&#xff0c;它描述了数据库的结构&#xff0c;包括表、视图、索引、存储过程、用户和其他数据库对象的信息。DBMS_METADATA 包允许用户…

安路FPGA开发工具TD:问题解决办法 及 Tips 总结

安路科技&#xff08;Anlogic&#xff09;是一家专注于高性能、低功耗可编程逻辑器件&#xff08;FPGA&#xff09;设计和生产的公司。其提供的开发工具TD&#xff08;TangDynasty&#xff09;是专门为安路FPGA系列产品设计的集成开发环境&#xff08;IDE&#xff09;。以下是对…

Java常用时间类

JDK7的时间类 1&#xff1a;Date类 2&#xff1a;SimpleDateFormat类 3&#xff1a;Calendar类 JDK8的时间类 1&#xff1a;Zoneld类 2&#xff1a;Instant类 3&#xff1a;ZoneDateTime 4&#xff1a;LocalDate 5&#xff1a;LocalTime 6&#xff1a;LocalDateTime …

模块化架构与微服务架构,哪种更适合桌面软件开发?

前言 在现代软件开发中&#xff0c;架构设计扮演着至关重要的角色。两种常见的架构设计方法是模块化架构与微服务架构。它们各自有独特的优势和适用场景&#xff0c;尤其在C#桌面软件开发领域&#xff0c;模块化架构往往更加具有实践性。本文将对这两种架构进行对比&#xff0…

Java开发提效秘籍:巧用Apache Commons IO工具库

一、引言 在 Java 开发的广袤领域中&#xff0c;输入输出&#xff08;I/O&#xff09;操作宛如一座桥梁&#xff0c;连接着程序与外部世界&#xff0c;从文件的读取与写入&#xff0c;到网络数据的传输&#xff0c;I/O 操作无处不在&#xff0c;其重要性不言而喻。然而&#xf…

使用 Helm 安装 Redis 集群

在 Kubernetes 集群中使用 Helm 安装 Redis 集群可以极大地简化部署和管理 Redis 的过程。本文将详细介绍如何使用 Helm 安装 Redis 集群&#xff0c;并提供一些常见问题的解决方案。 前提条件 Kubernetes 集群。&#xff08;略&#xff09;已安装 Helm 工具。搭建了存储类nf…

算法刷题笔记——图论篇

这里写目录标题 理论基础图的基本概念图的种类度 连通性连通图强连通图连通分量强连通分量 图的构造邻接矩阵邻接表 图的遍历方式 深度优先搜索理论基础dfs 与 bfs 区别dfs 搜索过程深搜三部曲所有可达路径广度优先搜索理论基础广搜的使用场景广搜的过程 岛屿数量孤岛的总面积沉…

C 语言的void*到底是什么?

一、void* 的类型任意性 void* 是一种通用指针类型。它可以指向任意类型的数据。例如&#xff0c;它可以指向一个整数&#xff08;int&#xff09;、一个浮点数&#xff08;float&#xff09;、一个字符&#xff08;char&#xff09;或者一个结构体等。在C语言中&#xff0c;当…

Redis延迟队列详解

以下是对 Redis 延迟队列的详细解释&#xff1a; 一、什么是 Redis 延迟队列 Redis 延迟队列是一种使用 Redis 实现的消息队列&#xff0c;其中的消息在被消费之前会等待一段时间&#xff0c;这段时间就是延迟时间。延迟队列常用于一些需要延迟处理的任务场景&#xff0c;例如订…