Redis场景问题1:缓存穿透

news2025/4/1 4:33:17

Redis 缓存穿透是指在缓存系统(如 Redis)中,当客户端请求的数据既不在缓存中也不在数据库中时,每次请求都会直接穿透缓存访问数据库,从而给数据库带来巨大压力,甚至可能导致数据库崩溃。下面为你详细介绍其产生原因、解决方案以及示例代码。

产生原因

  • 非法请求:恶意攻击者可能会故意发送大量不存在于数据库中的请求,使缓存失去作用,请求全部落到数据库上。
  • 业务逻辑错误:在业务开发过程中,如果对数据的判断逻辑有误,可能会导致程序请求不存在的数据。

解决方案

1. 缓存空对象

当请求的数据在数据库中不存在时,将一个空对象(如null"")存入缓存,并设置一个较短的过期时间。这样下次相同的请求就会直接从缓存中获取空对象,而不会再次访问数据库。

2. 布隆过滤器

布隆过滤器是一种空间效率极高的概率型数据结构,用于判断一个元素是否存在于一个集合中。在请求访问缓存之前,先通过布隆过滤器判断该请求的数据是否可能存在。如果布隆过滤器判断数据不存在,那么就直接返回,避免访问数据库。

示例代码(Python + Redis)

以下是使用 Python 和 Redis 实现缓存空对象的示例代码:

import redis

# 连接Redis
r = redis.Redis(host='localhost', port=6379, db=0)

def get_data(key):
    # 先从缓存中获取数据
    data = r.get(key)
    if data is not None:
        # 如果缓存中有数据,直接返回
        if data == b'':
            return None
        return data.decode('utf-8')
    else:
        # 缓存中没有数据,从数据库中获取(这里用模拟函数代替)
        data = get_data_from_db(key)
        if data is None:
            # 如果数据库中也没有数据,缓存空对象
            r.setex(key, 60, '')  # 设置过期时间为60秒
        else:
            # 数据库中有数据,存入缓存
            r.setex(key, 3600, data)  # 设置过期时间为3600秒
        return data

def get_data_from_db(key):
    # 模拟从数据库中获取数据
    # 这里可以替换为实际的数据库查询操作
    if key == 'existing_key':
        return 'some data'
    return None

# 测试
print(get_data('existing_key'))
print(get_data('non_existing_key'))

上述代码实现了一个简单的缓存空对象的机制,当请求的数据在数据库中不存在时,会将空对象存入缓存,避免下次请求再次访问数据库。

布隆过滤器示例(Python + RedisBloom)

如果你使用的是 RedisBloom 模块,可以使用布隆过滤器来解决缓存穿透问题:

from redisbloom.client import Client

# 连接RedisBloom
rb = Client()

# 初始化布隆过滤器
rb.bfCreate('mybloom', 0.01, 1000)  # 错误率为0.01,预计插入1000个元素

# 向布隆过滤器中添加元素
rb.bfAdd('mybloom', 'existing_key')

def get_data_with_bloom(key):
    # 先通过布隆过滤器判断元素是否可能存在
    if not rb.bfExists('mybloom', key):
        return None
    # 再从缓存中获取数据
    data = r.get(key)
    if data is not None:
        if data == b'':
            return None
        return data.decode('utf-8')
    else:
        data = get_data_from_db(key)
        if data is None:
            r.setex(key, 60, '')
        else:
            r.setex(key, 3600, data)
        return data

# 测试
print(get_data_with_bloom('existing_key'))
print(get_data_with_bloom('non_existing_key'))

上述代码使用了 RedisBloom 模块的布隆过滤器,在请求访问缓存之前,先通过布隆过滤器判断元素是否可能存在,从而减少不必要的数据库访问。

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

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

相关文章

从 MySQL 到时序数据库 TDengine:Zendure 如何实现高效储能数据管理?

小T导读:TDengine 助力广州疆海科技有限公司高效完成储能业务的数据分析任务,轻松应对海量功率、电能及输入输出数据的实时统计与分析,并以接近 1 : 20 的数据文件压缩率大幅降低存储成本。此外,taosX 强大的 transform 功能帮助用…

观察者模式:解耦对象间的依赖关系

观察者模式:解耦对象间的依赖关系 JDK 中曾直接提供对观察者模式的支持,但因其设计局限性,现已被标记为“过时”(Deprecated)。不过,观察者模式的思想在 JDK 的事件处理、spring框架等仍有广泛应用。下面我…

windows第二十章 单文档应用程序

文章目录 单文档定义新建一个单文档应用程序单文档应用程序组成:APP应用程序类框架类(窗口类)视图类(窗口类,属于框架的子窗口)文档类(对数据进行保存读取操作) 直接用向导创建单文档…

通信协议之串口

文章目录 简介电平标准串口参数及时序USART与UART过程引脚配置 简介 点对点,只能两设备通信只需单向的数据传输时,可以只接一根通信线当电平标准不一致时,需要加电平转换芯片(一般从控制器出来的是信号是TTL电平)地位…

Java入门知识总结——章节(二)

ps:本章主要讲数组、二维数组、变量 一、数组 数组是一个数据容器,可用来存储一批同类型的数据 🔑:注意 类也可以是一个类的数组 public class Main {public static class Student {String name;int age; // 移除 unsignedint…

Verilog 中寄存器类型(reg)与线网类型(wire)的区别

目录 一、前言 二、基本概念与分类 1.寄存器类型 2.线网类型 三、六大核心区别对比 四、使用场景深度解析 1.寄存器类型的典型应用 2. 线网类型的典型应用 五、常见误区与注意事项 1. 寄存器≠物理寄存器 2.未初始化值陷阱 3.SystemVerilog的改进 六、总结 …

【Linux加餐-验证UDP:TCP】-windows作为client访问Linux

一、验证UDP-windows作为client访问Linux UDP client样例代码 #include <iostream> #include <cstdio> #include <thread> #include <string> #include <cstdlib> #include <WinSock2.h> #include <Windows.h>#pragma warning(dis…

Rust vs. Go: 性能测试(2025)

本内容是对知名性能评测博主 Anton Putra Rust vs. Go (Golang): Performance 2025 内容的翻译与整理, 有适当删减, 相关数据和结论以原作结论为准。 再次对比 Rust 和 Go&#xff0c;但这次我们使用的是最具性能优势的 HTTP 服务器库---Hyper&#xff0c;它基于 Tokio 异步运…

JDBC的详细使用

1. JDBC概述 JDBC[Java Database Connectivity]是 Java 语言中用于连接和操作数据库的一套标准 API。它允许 Java 程序通过统一的方式与各种关系型数据库&#xff0c;如 MySQL、Oracle、SQL Server 等交互&#xff0c;执行 SQL 语句并处理结果。 1.1 JDBC原理 JDBC的核心原理…

瑞芯微 RKrga接口 wrapbuffer_virtualaddr 使用笔记

一、源码 官方在librga中给了很多 demo 以供参考&#xff0c;例如 imresize 操作&#xff1a; /** Copyright (C) 2022 Rockchip Electronics Co., Ltd.* Authors:* YuQiaowei <cerf.yurock-chips.com>** Licensed under the Apache License, Version 2.0 (the &qu…

【数据结构】[特殊字符] 并查集优化全解:从链式退化到近O(1)的性能飞跃 | 路径压缩与合并策略深度实战

并查集的优化 导读一、合并优化1.1 基本原理1.2 按大小合并1.3 按秩合并1.4 两种合并的区别**1.4.1 核心目标****1.4.2 数据存储****1.4.3 合并逻辑****1.4.4 树高控制****1.4.5 适用场景****1.4.6 路径压缩兼容性****1.4.7 极端案例对比****1.4.8 小结**二、查找优化2.1 路径压…

如何在 AI 搜索引擎(GEO)霸屏曝光,快速提升知名度?

虽然大多数人仍然使用 Google 来寻找答案&#xff0c;但正在发生快速转变。ChatGPT、Copilot、Perplexity 和 DeepSeek 等 LLM 已成为主流。这主要是因为每个都有自己的免费和公共版本&#xff0c;并且总是有重大的质量改进。 许多人每天都使用这些工具来提问和搜索互联网&…

VLAN综合实验二

一.实验拓扑&#xff1a; 二.实验需求&#xff1a; 1.内网Ip地址使用172.16.0.0/分配 2.sw1和SW2之间互为备份 3.VRRP/STP/VLAN/Eth-trunk均使用 4.所有Pc均通过DHCP获取IP地址 5.ISP只能配置IP地址 6.所有…

Kubernetes》k8s》Containerd 、ctr 、cri、crictl

containerd ctr crictl ctr 是 containerd 的一个客户端工具。 crictl 是 CRI 兼容的容器运行时命令行接口&#xff0c;可以使用它来检查和调试 k8s 节点上的容器运行时和应用程序。 ctr -v 输出的是 containerd 的版本&#xff0c; crictl -v 输出的是当前 k8s 的版本&#x…

SQL语句及其应用(中)(DQL语句之单表查询)

SQL语句的定义: 概述: 全称叫 Structured Query Language, 结构化查询语言, 主要是实现 用户(程序员) 和 数据库软件(例如: MySQL, Oracle)之间交互用的. 分类: DDL: 数据定义语言, 主要是操作 数据库, 数据表, 字段, 进行: 增删改查(CURD) 涉及到的关键字: create, drop, …

算法题(111):k与迷宫

审题&#xff1a; 本题需要我们寻找迷宫中的所有出口&#xff0c;若有出口需要输出距离最近的出口的距离&#xff0c;若没有就输出-1 时间复杂度&#xff1a;由于边距为1&#xff0c;我们本题采用bfs算法&#xff0c;在最坏的情况下我们需要遍历所有位置&#xff0c;时间复杂度…

Redis-常用命令

目录 1、Redis数据结构 2、命令简介 2.1、通用命令 DEL EXISTS EXPIRE 2.2、String命令 SET和GET MSET和MGET INCR和INCRBY和DECY SETNX SETEX 2.3、Key的层级结构 2.4、Hash命令 HSET和HGET HMSET和HMGET HGETALL HKEYS和HVALS HINCRBY HSETNX 2.5、List命…

从虚拟现实到可持续设计:唐婉歆的多维创新之旅

随着线上线下融合逐渐成为全球家居与建材行业的发展趋势,全球市场对高品质、个性化家居和建材产品的需求稳步攀升,也对设计师提出更高的要求。在这一背景下,设计师唐婉歆将以产品设计师的身份,正式加入跨国企业AmCan 美加集团,投身于备受行业瞩目的系列设计项目。她将负责Showr…

音视频 四 看书的笔记 MediaPlayerService

Binder机制看这里 Binde机智 这是一个分割符 Binder机智 分割(goutou) Binder机制 MediaPlayerService多媒体框架中一个非常重要的服务。MediaPlayerService 我原称之为链接之王 图片来源 MediaPlayer 是客户端 C/S 中的CMediaPlayerService MediaPlayerService::Client 是服…

vmware 创建win10 系统,虚拟机NAT网络设置

虚拟机设置&#xff1a; 物理机本机创建桥接&#xff1a; 如何创建桥接&#xff0c;请自行脑补~