什么是缓存击穿?如何避免之布隆过滤器

缓存击穿(Cache Penetration)是分布式系统和缓存使用中的一个常见问题,布隆过滤器在解决缓存击穿问题时非常有用。接下来我会介绍缓存击穿的概念以及布隆过滤器在解决该问题中的应用。

什么是缓存击穿?

缓存击穿是指当大量的客户端请求访问一个不存在的缓存数据时,这些请求会绕过缓存直接击穿到数据库,给数据库带来巨大压力,甚至可能导致服务瘫痪。这通常发生在以下几种情况下:

  1. 请求的键不存在于缓存中:比如用户在查询一个不存在的商品 ID、文章 ID 等。
  2. 缓存未命中:由于查询到的结果不存在,直接请求数据库,这种请求行为在高并发场景下,会对数据库产生非常大的压力。

缓存击穿的场景

  • 假设你有一个大型电商网站,客户经常搜索商品。某些时候,一些用户会输入随机的 ID 进行商品搜索。如果这些 ID 是无效的,且对应的数据并不在数据库中,查询结果也不会被缓存。这些请求会不断地穿透缓存,直接访问数据库,导致数据库负载过高。
  • 在这种情况下,大量查询无效键的请求绕过缓存,直接访问数据库,使得数据库变得不堪重负,甚至宕机。

布隆过滤器在解决缓存击穿中的应用

布隆过滤器可以有效地解决缓存击穿问题,原因是它可以快速判断一个键是否一定不存在,从而避免对数据库的无效查询。

布隆过滤器如何应用于缓存击穿?
  1. 初始化阶段

    • 在系统启动或初始化时,将所有数据库中的有效键(比如商品 ID)加载到布隆过滤器中。布隆过滤器中记录了所有有效键的信息。
  2. 请求阶段

    • 当客户端请求某个键时,首先使用布隆过滤器进行检查。
    • 布隆过滤器判断
      • 如果布隆过滤器判断该键一定不存在(即返回 false),那么直接返回结果为 “无数据”。
      • 如果布隆过滤器判断该键可能存在(即返回 true),则继续查询缓存。
      • 如果缓存命中,返回缓存结果;如果缓存未命中,查询数据库。
  3. 查询数据库

    • 如果布隆过滤器判断该键可能存在,且缓存也没有结果,最终的查询会走到数据库。
    • 如果数据库也没有结果,通常可以将结果设置为一个“空对象”并加入缓存,以防止短时间内再度访问造成缓存击穿。
布隆过滤器解决缓存击穿的好处
  1. 减少数据库的访问

    • 布隆过滤器在大多数情况下可以直接判断无效的请求,从而不必查询数据库,这样可以减少对数据库的压力。
  2. 高效的存在性判断

    • 布隆过滤器使用位数组和多个哈希函数,可以在常数时间复杂度 O(k)(k 为哈希函数个数)内完成存在性判断,并且占用的空间非常小。
示例:布隆过滤器用于防止缓存击穿

以下是一个简单的示例,演示如何利用布隆过滤器来防止缓存击穿。

import java.util.BitSet;

public class CacheWithBloomFilter {
    private static final int DEFAULT_SIZE = 1000; // 位数组大小
    private static final int[] SEEDS = new int[]{7, 11, 13, 31, 37, 61}; // 哈希函数种子
    private BitSet bits;
    private HashFunction[] hashFunctions;

    public CacheWithBloomFilter() {
        bits = new BitSet(DEFAULT_SIZE);
        hashFunctions = new HashFunction[SEEDS.length];
        for (int i = 0; i < SEEDS.length; i++) {
            hashFunctions[i] = new HashFunction(DEFAULT_SIZE, SEEDS[i]);
        }
        // 模拟初始化阶段,将数据库中有效的数据加载到布隆过滤器
        String[] existingKeys = {"product_1", "product_2", "product_3"};
        for (String key : existingKeys) {
            add(key);
        }
    }

    // 添加元素到布隆过滤器
    public void add(String value) {
        for (HashFunction f : hashFunctions) {
            bits.set(f.hash(value), true);
        }
    }

    // 查询元素是否存在
    public boolean mightContain(String value) {
        for (HashFunction f : hashFunctions) {
            if (!bits.get(f.hash(value))) {
                return false; // 如果有一个哈希值位置为 0,则说明一定不存在
            }
        }
        return true; // 所有位都为 1,则说明可能存在
    }

    // 模拟缓存查询
    public String getFromCache(String key) {
        // 在布隆过滤器中检查是否可能存在
        if (!mightContain(key)) {
            System.out.println("Key '" + key + "' is not in bloom filter, skipping cache and DB lookup.");
            return null; // 一定不存在
        }
        // 模拟缓存查询(这里假设缓存总是未命中)
        System.out.println("Key '" + key + "' might be in bloom filter, continue cache lookup...");
        return null; // 模拟缓存未命中
    }

    // 模拟数据库查询
    public String getFromDB(String key) {
        // 模拟数据库查询(这里假设部分键不存在)
        System.out.println("Querying database for key '" + key + "'...");
        if ("product_1".equals(key) || "product_2".equals(key) || "product_3".equals(key)) {
            return "Valid Product";
        }
        return null; // 数据库中不存在该键
    }

    public static void main(String[] args) {
        CacheWithBloomFilter cache = new CacheWithBloomFilter();

        // 查询不存在的键,布隆过滤器返回一定不存在
        cache.getFromCache("product_100"); // 布隆过滤器直接拒绝

        // 查询可能存在的键
        cache.getFromCache("product_1");
        cache.getFromDB("product_1"); // 继续查询数据库
    }

    // 内部静态类,定义哈希函数
    private static class HashFunction {
        private int cap;
        private int seed;

        public HashFunction(int cap, int seed) {
            this.cap = cap;
            this.seed = seed;
        }

        public int hash(String value) {
            int result = 0;
            for (int i = 0; i < value.length(); i++) {
                result = seed * result + value.charAt(i);
            }
            return (cap - 1) & result; // 返回在 [0, cap) 范围内
        }
    }
}

解释代码

  1. 布隆过滤器初始化

    • 将数据库中所有有效的键(例如 "product_1", "product_2", "product_3")都添加到布隆过滤器中。
  2. 查询流程

    • 当查询一个不存在的键 "product_100" 时,布隆过滤器直接判断该键不存在,从而避免了数据库查询。
    • 当查询一个可能存在的键 "product_1" 时,布隆过滤器判断该键可能存在,于是继续进行缓存查询或者数据库查询。

总结布隆过滤器在缓存击穿中的作用

  • 快速判断无效键:布隆过滤器可以高效地判断某个键是否存在。如果布隆过滤器判定某个键一定不存在,那么请求不会再访问缓存和数据库,从而减少无效请求对系统的压力。
  • 减少数据库压力:通过布隆过滤器,可以有效减少对数据库的无效访问,从而防止缓存击穿给数据库带来的高并发压力。

布隆过滤器的这种使用场景,在实际的大规模系统中非常常见,尤其是在需要减少数据库访问次数、保护数据库负载的系统中,如分布式缓存系统、API 限流、去重等场景。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【回文数组——另类递推】

题目 代码 #include <bits/stdc.h> using namespace std; using ll long long; const int N 1e510; int a[N], b[N]; int main() {int n;cin >> n;for(int i 1; i < n; i)cin >> a[i];for(int i 1; i < n / 2; i)b[i] a[i] - a[n1-i];ll ans 0;…

scala统计词频

package test23import java.io.PrintWriter import scala.io.Source object test {def main(args: Array[String]): Unit {//从文件1.txt中&#xff0c;读取内容val content Source.fromFile("1.txt").mkStringprintln(content)//把字符串中的每个单词&#xff0c;…

数据结构——排序算法第二幕(交换排序:冒泡排序、快速排序(三种版本) 归并排序:归并排序(分治))超详细!!!!

文章目录 前言一、交换排序1.1 冒泡排序1.2 快速排序1.2.1 hoare版本 快排1.2.2 挖坑法 快排1.2.3 lomuto前后指针 快排 二、归并排序总结 前言 继上篇学习了排序的前面两个部分:直接插入排序和选择排序 今天我们来学习排序中常用的交换排序以及非常稳定的归并排序 快排可是有多…

Android基本概念及控件

Android是Google公司基于Linux平台开发的主要应用于智能手机及平板电脑的操作系统。 ART模式与Dalvik模式最大的不同在于:在启用ART模式后&#xff0c;系统在安装应用程序的时候会进行一次预编译&#xff0c;并先将代码转换为机器语言存储在本地,这样在运行程序时就不会每次都…

【JavaEE初阶 — 网络编程】Socket 套接字 & UDP数据报套接字编程

1. Socket套接字 1.1 概念 Socket 套接字&#xff0c;是由系统提供用于网络通信的技术&#xff0c;是基于TCP / IP协议的网络通信的基本操作单元。基于 Socket 套接字的网络程序开发就是网络编程。 1.2 分类 Socket套接字主要针对传输层协议划分为如下三类&#x…

Leecode刷题C语言之交替组②

执行结果:通过 执行用时和内存消耗如下&#xff1a; 代码如下&#xff1a; int numberOfAlternatingGroups(int* colors, int colorsSize, int k) {int res 0, cnt 1;for (int i -k 2; i < colorsSize; i) {if (colors[(i colorsSize) % colorsSize] ! colors[(i - …

科技惊艳:RFID技术引领被装物联网信息化革新

被装物联网信息化监控系统是一项错综复杂却成效斐然的解决方案&#xff0c;它巧妙地将物联网技术的先进性与装设备资源管理的实际需求相融合&#xff0c;实现了对被装设备资源的即时追踪、智能化调控以及资源的最优化配置。以下是对被装物联网的深度剖析与高端解读&#xff1a;…

360推出全新的生成式 AI 搜索产品:纳米搜索,要重塑搜索产品

【大力财经】直击互联网最前线&#xff1a;360 集团在 2024 年 11 月 27 日开发布会&#xff0c;重磅推出了一款全新的生成式 AI 搜索产品——纳米搜索&#xff0c;并且已经上架到苹果 App Store 以及应用宝等安卓应用商店&#xff0c;直接与百度、阿里夸克、秘塔 AI、Perplexi…

Android Deep Links 深度链接解析

在实现 Android 应用链接之前&#xff0c;请务必了解您可以在 Android 应用中创建的不同类型的链接&#xff1a;深层链接、网页链接和 Android 应用链接。 Android Deep Links 深度链接解析 一、什么是Deep Links&#xff1f;二、Deep Links的优势三、Deep Links的实现方式1. …

setter方法注入(Java EE 学习笔记07)

属性setter方法注入是Spring最主流的注入方法&#xff0c;这种注入方法简单、直观&#xff0c;它是在被注入的类中声明一个setter方法&#xff0c;通过setter方法的参数注入对应的值。 案例&#xff1a; ① 创建User2实体&#xff0c;配置setter方法 package com.lq.entities…

英语知识网站:Spring Boot技术构建

6系统测试 6.1概念和意义 测试的定义&#xff1a;程序测试是为了发现错误而执行程序的过程。测试(Testing)的任务与目的可以描述为&#xff1a; 目的&#xff1a;发现程序的错误&#xff1b; 任务&#xff1a;通过在计算机上执行程序&#xff0c;暴露程序中潜在的错误。 另一个…

2025蓝桥杯(单片机)备赛--扩展外设之UART1的原理与应用(十二)

一、串口1的实现原理 a.查看STC15F2K60S2数据手册: 串口一在590页&#xff0c;此款单片机有两个串口。 串口1相关寄存器&#xff1a; SCON:串行控制寄存器&#xff08;可位寻址&#xff09; SCON寄存器说明&#xff1a; 需要PCON寄存器的SMOD0/PCON.6为0&#xff0c;使SM0和SM…

利用Python爬取12306网站车次信息

前言 随着互联网技术的发展,网络爬虫成为了获取公开数据的强大工具之一。对于经常需要查询火车票信息的人来说,能够自己编写一个爬虫程序来自动获取并整理这些信息,无疑是一个非常实用的技能。本文将详细介绍如何使用Python爬取12306网站上的车次信息,包括获取站点对应城市…

React Hooks中use的细节

文档 useState useState如果是以函数作为参数&#xff0c;那要求是一个纯函数&#xff0c;不接受任何参数&#xff0c;同时需要一个任意类型的返回值作为初始值。 useState可以传入任何类型的参数作为初始值&#xff0c;当以一个函数作为参数进行传入的时候需要注意&#xff…

2024 TIP 论文 robust-ref-seg 复现过程

本篇是 2024 年 TIP 论文 Toward Robust Referring Image Segmentation 的复现过程。 特点是对不存在的目标不会进行错误分割&#xff0c;鲁棒性较高&#xff0c;其结果如图&#xff1a; 配置环境 根据论文给出的链接 robust-ref-seg 配置环境。 下载数据集 按照 README 指…

数据结构(初阶6)---二叉树(遍历——递归的艺术)(详解)

二叉树的遍历与练习 一.二叉树的基本遍历形式1.前序遍历(深度优先遍历)2.中序遍历(深度优先遍历)3.后序遍历(深度优先遍历)4.层序遍历&#xff01;&#xff01;(广度优先遍历) 二.二叉树的leetcode小练习1.判断平衡二叉树1&#xff09;正常解法2&#xff09;优化解法 2.对称二叉…

k8s集群增加nfs-subdir-external-provisioner存储类

文章目录 前言一、版本信息二、本机安装nfs组件包三、下载nfs-subdir-external-provisioner配置文件并进行配置1.下载文件2.修改配置 三、进行部署备注&#xff1a;关于镜像无法拉取问题的处理 前言 手里的一台服务器搭建一个单点的k8s集群&#xff0c;然后在本机上使用nfs-su…

C++ For Hot100

数组&#xff1a;数组是存放在连续内存空间上的相同类型数据的集合。 1. 两数之和 - 力扣&#xff08;LeetCode&#xff09; class Solution { public:vector<int> twoSum(vector<int>& nums, int target) {vector<int> v;for(int i 0;i<nums.size…

高校宿舍节能用电现状及智慧监管平台构建

0 引言 在节能减排的大背景下&#xff0c;高校通过精细化宿舍用电管理&#xff0c;提升师生的节能节电意识等举措&#xff0c;能够显著提高电能资源的使用效率&#xff0c;并有效预防火灾等安全事故&#xff0c;确保师生的人身安全。因此&#xff0c;当前亟需加强对智慧监管平…

Spring Boot英语知识网站:开发策略

5系统详细实现 5.1 管理员模块的实现 5.1.1 用户信息管理 英语知识应用网站的系统管理员可以对用户信息添加修改删除以及查询操作。具体界面的展示如图5.1所示。 图5.1 用户信息管理界面 5.1.2 在线学习管理 系统管理员可以对在线学习信息进行添加&#xff0c;修改&#xff0…