如何使用 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.rhkb.cn/news/6047.html

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

相关文章

【玩转全栈】----Django基本配置和介绍

目录 Django基本介绍: Django基本配置: 安装Django 创建项目 创建app 注册app Django配置路由URL Django创建视图 启动项目 Django基本介绍: Django是一个开源的、基于Python的高级Web框架,旨在以快速、简洁的方式构建高质量的Web…

RabbitMQ 高级特性

目录 1.消息确认 1.1 消息确认机制 1.2 手动确认方法 1. 2.1肯定确认 1.2.2 否定确认 1.3 SpringBoot 代码示例 1.3.1 配置确认机制 1.3.2 配置队列,交换机,绑定关系 1.3.3 生产者(向 rabbitmq 发送消息) 1.3.4 消费者(消费队列中的信息) 2.持久性 2.1 交换机…

QT:控件属性及常用控件(3)-----输入类控件(正则表达式)

输入类控件既可以进行显示,也能让用户输入一些内容! 文章目录 1.Line Edit1.1 用户输入个人信息1.2 基于正则表达式的文本限制1.3 验证两次输入的密码是否一致1.4 让输入的密码可以被查看 2.Text Edit2.1 输入和显示同步2.1 其他信号出发情况 3.ComboBox…

迅为RK3568开发板篇OpenHarmony实操HDF驱动控制LED-添加内核编译

编译内核时将该 HDF 驱动编译到镜像中,接下来编写驱动编译脚本 Makefile,代码如下所示: 加入编译体系,填加模块目录到 drivers/hdf_core/adapter/khdf/linux/Makefile 文件 更多内容可以关注:迅为RK3568开发板篇OpenHa…

【面试总结】FFN(前馈神经网络)在Transformer模型中先升维再降维的原因

FFN(前馈神经网络)在Transformer模型中先升维再降维的设计具有多方面的重要原因,以下是对这些原因的总结: 1.目标与动机 高维映射空间:FFN的设计目的是通过一系列线性变换来拟合一个高维的映射空间,而不仅…

从零安装 LLaMA-Factory 微调 Qwen 大模型成功及所有的坑

文章目录 从零安装 LLaMA-Factory 微调 Qwen 大模型成功及所有的坑一 参考二 安装三 启动准备大模型文件 四 数据集(关键)!4.1 Alapaca格式4.2 sharegpt4.3 在 dataset_info.json 中注册4.4 官方 alpaca_zh_demo 例子 999条数据, 本机微调 5分…

【Rabbitmq】Rabbitmq高级特性-发送者可靠性

Rabbitmq发送者可靠性 发送者重连发送者确认1.开启确认机制2.ReturnCallback3.ConfirmCallback MQ的可靠性数据持久化交换机持久化队列持久化消息持久化 Lazy Queue 总结其他文章 Rabbitmq提供了两种发送来保证发送者的可靠性,第一种叫发送者重连,第二种…

计算机网络 (55)流失存储音频/视频

一、定义与特点 定义:流式存储音频/视频是指经过压缩并存储在服务器上的多媒体文件,客户端可以通过互联网边下载边播放这些文件,也称为音频/视频点播。 特点: 边下载边播放:用户无需等待整个文件下载完成即可开始播放…

抖音小程序一键获取手机号

前端代码组件 <button v-if"!isFromOrderList"class"get-phone-btn" open-type"getPhoneNumber"getphonenumber"onGetPhoneNumber">一键获取</button>// 获取手机号回调onGetPhoneNumber(e) {var that this tt.login({f…

论文速读|NoteLLM: A Retrievable Large Language Model for Note Recommendation.WWW24

论文地址&#xff1a;https://arxiv.org/abs/2403.01744 bib引用&#xff1a; misc{zhang2024notellmretrievablelargelanguage,title{NoteLLM: A Retrievable Large Language Model for Note Recommendation}, author{Chao Zhang and Shiwei Wu and Haoxin Zhang and Tong Xu…

Day 15 卡玛笔记

这是基于代码随想录的每日打卡 222. 完全二叉树的节点个数 给你一棵 完全二叉树 的根节点 root &#xff0c;求出该树的节点个数。 完全二叉树 的定义如下&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没填满外&#xff0c;其余每层节点数都达到最大值&#x…

【阿里云】使用docker安装nginx后可以直接访问

一、创建目录 mkdir -p config/{cert,conf.d} html logs二、上传nginx.conf的配置文件 user nginx; worker_processes auto;error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid;events {worker_connections 1024; }http {include /etc/ngin…

在elasticsearch中,document数据的写入流程如何?

本文将为您介绍文档内容是如何写入ES集群中。 数据写入ES集群的流程图如下 流程介绍 用户携带数据发起POST请求指向集群9200端口。9200端口将数据写入请求发给主分片。主分片会对数据进行分片计算分发给具体分片。&#xff08;计算方式&#xff1a;hash % primary_number_sha…

sentinel微服务保护

学习链接 SpringCloudRabbitMQDockerRedis搜索分布式 文章目录 学习链接1.初识Sentinel1.1.雪崩问题及解决方案1.1.1.雪崩问题1.1.2.超时处理1.1.3.仓壁模式1.1.4.断路器1.1.5.限流1.1.6.总结 1.2.服务保护技术对比1.3.Sentinel介绍和安装1.3.1.初识Sentinel官网地址github地址…

STM32-CAN总线

1.CAN总线简介 CAN总线是由BOSCH公司开发的一种简洁易用、传输速度快、易扩展、可靠性高的串行通信总线 2.CAN总线特征 两根通信线&#xff08;CAN_H、CAN_L&#xff09;&#xff0c;线路少&#xff0c;无需共地差分信号通信&#xff08;相对的是单端信号&#xff09;&#…

iOS 权限管理:同时请求相机和麦克风权限的最佳实践

引言 在开发视频类应用时&#xff0c;我们常常会遇到需要同时请求相机和麦克风权限的场景。比如&#xff0c;在用户发布视频动态时&#xff0c;相机用于捕捉画面&#xff0c;麦克风用于录制声音&#xff1b;又或者在直播功能中&#xff0c;只有获得这两项权限&#xff0c;用户…

DDD实战课 笔记

DDD实战课 作者&#xff1a;欧创新 01 | 微服务设计为什么要选择DDD&#xff1f; 微服务拆分困境产生的根本原因就是不知道业务或者微服务的边界到底在什么地方。 为什么 DDD 适合微服务&#xff1f; DDD 是一种处理高度复杂领域的设计思想&#xff0c;它试图分离技术实现的…

数据结构——算法基础

1、概念 算法(Algorithm)用来描述对特定问题的求解步骤&#xff0c;它是指令的有限序列&#xff0c;其中每一条指令代表一个或多个操作 算法的概念在计算机科学领域中几乎无处不在&#xff0c;在各种计算机系统的实现中&#xff0c;算法的设计往往处于核心的位置。计算机的问…

Glary Utilities Pro 多语便携版系统优化工具 v6.21.0.25

Glary Utilities是一款功能强大的系统优化工具软件&#xff0c;旨在帮助用户清理计算机垃圾文件、修复系统错误、优化系统性能等。 软件功能 清理和修复&#xff1a;可以清理系统垃圾文件、无效注册表项、无效快捷方式等&#xff0c;修复系统错误和蓝屏问题。 优化和加速&…

USART_串口通讯轮询案例(HAL库实现)

引言 前面讲述的串口通讯案例是使用寄存器方式实现的&#xff0c;有利于深入理解串口通讯底层原理&#xff0c;但其开发效率较低&#xff1b;对此&#xff0c;我们这里再讲基于HAL库实现的串口通讯轮询案例&#xff0c;实现高效开发。当然&#xff0c;本次案例需求仍然和前面寄…