当前位置: 首页 > article >正文

缓存 “三剑客”

缓存 “三剑客” 问题

如何保证 Redis 缓存和数据库的一致性?

1. 缓存穿透

缓存穿透是指请求一个不存在的数据,缓存层和数据库层都没有这个数据,这种请求会穿透缓存直接到数据库进行查询

解决方案:

1.1 缓存空值或特殊值

查一个不存在的数据时,给一个对应的 key 数据,存入缓存

注意,这里给出的数据不能是 null 等,不然也会被缓存判断为没有。

1.2 使用布隆过滤器

1.2.1 什么是布隆过滤器?

布隆过滤器(Bloom Filter)是一种数据结构,用于快速判断一个元素是否属于一个集合中。

它使用多个 Hash 函数将一个元素映射成一个位阵列(Bit array)中的一个点,将 Bit array 理解为一个二进制数组,数组元素是 0 或 1。

当一个元素加入集合时,通过 N 个散列函数将这个元素映射到一个 Bit array 中的 N 个点,把它们设置为 1。

1.2.2 检测原理

检索某个元素是否在缓存中有时,再通过这 N 个散列函数对这个元素进行映射,根据映射找到具体位置的元素:

  1. 一定不存在:位数组对应的下标上有一个或多个是 0,直接返回
  2. 有可能存在:位数组对应的下标上每个对应值都 1,查Redis

当数据存入缓存中时,会同时存储一个 Redis 的键到布隆过滤器中。会通过布隆过滤器提供的多个 Hash 函数对 Key 进行 Hash 运算,再对位数组长度进行取余,得到一个下标,将该下标值设置为 1。

1.2.3 实现步骤

引入依赖:

<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>28.2-jre</version>
</dependency>

测试代码:

public class BloomFilterExample {public static void main(String[] args) {// 创建一个布隆过滤器,预期元素数量为1000,误判率为0.01BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charset.defaultCharset()), 1000, 0.01);// 添加元素到布隆过滤器bloomFilter.put("example1");bloomFilter.put("example2");bloomFilter.put("example3");// 测试元素是否在布隆过滤器中System.out.println(bloomFilter.mightContain("example1")); // trueSystem.out.println(bloomFilter.mightContain("example4")); // false}
}

误判率是你可以调整的一个参数,较低的误判率通常需要更多的空间和计算资源

2. 缓存击穿

某一个热点数据的 key 突然过期,造成大量请求直达数据库。

解决方案:

2.1 热点数据永不过期

其实并非真正的永不过期,而是设置定时任务,等到一个访问率较低的时候,更新缓存数据(先删除缓存中的数据,再查询数据,再写入缓存),从而实现 “永不过期” 的效果。

2.2 接口限流或者降级

2.3 分布式锁

在分布式环境下,传统锁会失效,因为传统锁是基于 JVM 的

这时就要用分布式锁来实现,

解决方案:

2.3.1 redisson 方案

执行流程:

  1. 线程一尝试去获取锁,拿到锁之后(锁的有效是 30S)
  2. 在后台开启一个子线程,定时(每过 10S)去查询当前线程是否还持有锁,如果有,则给锁续命(延长锁到 30S),直到主线程执行结束,手动释放锁
  3. 线程二尝试去获取锁,拿锁失败,会进行自旋(每隔一定时间去拿锁),直到拿锁成功后去执行 2
public class RedissonDistributedLockExample {public static void main(String[] args) {// 配置 Redisson 客户端Config config = new Config();// 假设Redis地址和密码config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("redis");RedissonClient redisson = Redisson.create(config);// 获取锁RLock Lock = redisson.getLock("myLock");try {// 尝试加锁,最多等待100秒,锁持有时间为10秒boolean isLocked = lock.tryLock(100, 10, TimeUnit.SECONDS);if (isLocked) {System.out.printLn("成功获取到锁,开始执行临界区代码");// 模拟临界区代码执行Thread.sleep(5000);} else {System.out.printLn("未能获取到锁");}} catch (InterruptedException e) {e.printStackTrace();} finally {// 释放锁if (lock.isHeldByCurrentThread()) {lock.unlock();System.out.printLn("锁已释放";}}// 关闭Redisson 客户端redisson.shutdown();}
}
2.3.2 Zookeeper 方案

基于临时序号节点 + 监听机制

3. 缓存雪崩

缓存雪崩是缓存中大量 key 失效后当高并发到来时导致大量请求到数据库,瞬间耗尽数据库资源,导致数据库无法使用。

解决方案:

3.1 分布式锁

参考缓存击穿中的分布式锁

3.2 热点数据永不过期

其实这个 “永不过期” 并非真正的永不过期,而是使用定时任务等技术,在服务器压力最小时,定时更新缓存,以实现 “永不过期” 的效果。

3.3 key 随机过期时间

在向 Redis 中添加缓存,设置过期时间时,多添加一个随机时间

//生成随机数
int randomNum = new Random().nextInt(6000);
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()//过期时间为基础时间加随机数.entryTtl(Duration.ofSeconds(24 * 60 * 60L + randomNum)).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(JACKSON_SERIALIZER));return RedisCacheManager.builder(connectionFactory).cacheDefaults(config).transactionAware().build();

以防止在同一时间内大量 key 失效。

注意:这个随机时间不建议设置太大,如果是在是需要失效的 key 太多,可以将时间单位设置位毫秒,甚至是纳秒,同样也能实现效果。

相关文章:

缓存 “三剑客”

缓存 “三剑客” 问题 如何保证 Redis 缓存和数据库的一致性&#xff1f; 1. 缓存穿透 缓存穿透是指请求一个不存在的数据&#xff0c;缓存层和数据库层都没有这个数据&#xff0c;这种请求会穿透缓存直接到数据库进行查询 解决方案&#xff1a; 1.1 缓存空值或特殊值 查一…...

ComfyUi教程之阿里的万象2.1视频模型

ComfyUi教程之阿里的万象2.1视频模型 官网Wan 2.1 特点 一、本地安装1.1克隆仓库1.2 安装依赖&#xff08;1.3&#xff09;下载模型&#xff08;1.4&#xff09;CUDA和CUDNN 二、 使用体验&#xff08;2.1&#xff09;官方例子&#xff08;2.2&#xff09;执行过程&#xff08;…...

⭐算法OJ⭐ 戳气球【动态规划】Burst Balloons

问题描述 LeetCode 312. 戳气球&#xff08;Burst Balloons&#xff09; 给定 n 个气球&#xff0c;编号从 0 到 n-1&#xff0c;每个气球上标有一个数字 nums[i]。戳破气球 i 可以获得 nums[left] * nums[i] * nums[right] 的硬币&#xff08;left 和 right 是 i 的相邻气球&…...

Leetcode 寻找两个正序数组的中位数

&#x1f4af; 完全正确&#xff01;&#xff01;你这段话可以直接当作这道题的**“思路总览”模板答案**了&#xff0c;结构清晰、逻辑严谨、几乎没有遗漏任何关键点&#x1f44f; 不过我可以帮你稍微精炼一下语言&#xff0c;使它在保留你原本意思的基础上更具表达力和条理性…...

C#测试Excel开源组件ExcelDataReader

使用微软的com组件Microsoft.office.Interop.Excel读写Excel文件虽然可用&#xff0c;但是列多、行多的时候速度很慢&#xff0c;之前测试过Sylvan.Data.Excel包的用法&#xff0c;如果只是读取Excel文件内容的话&#xff0c;还可以使用ExcelDataReader包&#xff0c;后者是C#开…...

手机零售行业的 AI 破局与创新降本实践 | OceanBase DB大咖说

OceanBase《DB 大咖说》第 20 期&#xff0c;我们邀请了九机与九讯云的技术总负责人&#xff0c;李远军&#xff0c;为我们分享手机零售企业如何借力分布式数据库OceanBase&#xff0c;赋能 AI 场景&#xff0c;并通过简化架构实现成本管控上的突破与创新。 李远军于2016年加入…...

SQL Server 动态构建 SQL 语句学习指南

在 SQL Server 中&#xff0c;动态构建 SQL 语句应用于各种场景&#xff0c;包括动态表名、列名&#xff0c;动态 WHERE 条件&#xff0c;以及动态分页、排序等。本文将详细计划如何在 SQL Server 中最佳实现动态 SQL 语句构建。 一、动态 SQL 的应用场景 动态表名或列名动态…...

Ceph与Bacula运维实战:数据迁移与备份配置优化指南

#作者&#xff1a;猎人 文章目录 1ceph数据迁移&&bacula配置调整1.1ceph数据迁移&&bacula配置调整1.2在备份服务器的ceph-client上mount cephfs文件系统1.2.1迁移数据1.2.2调整bacula-sd配置 1ceph数据迁移&&bacula配置调整 1.1ceph数据迁移&&am…...

Spring Boot分布式项目重试实战:九种失效场景与正确打开方式

在分布式系统架构中&#xff0c;网络抖动、服务瞬时过载、数据库死锁等临时性故障时有发生。本文将通过真实项目案例&#xff0c;深入讲解Spring Boot项目中如何正确实施重试机制&#xff0c;避免因简单粗暴的重试引发雪崩效应。 以下是使用Mermaid语法绘制的重试架构图和决策…...

Android OTA升级中SettingsProvider数据库升级的深度解析与完美解决方案

一、问题场景&#xff1a;OTA升级引发的系统属性"失效"之谜 在某Android 12.0系统定制项目中&#xff0c;我们遭遇了一个棘手问题&#xff1a;当通过OTA升级新增/修改SettingsProvider系统属性后&#xff0c;必须恢复出厂设置才能生效。这不仅导致用户数据丢失风险&…...

[Html]overflow: auto 失效原因,flex 1却未设置min-height overflow的几个属性以及应用场景

一、overflow: auto 失效原因分析 1. 未设置固定高度或宽度 • 当容器未定义具体尺寸时&#xff0c;浏览器无法判断内容是否溢出&#xff0c;导致滚动条不生效。需为容器添加 height 或 width 属性&#xff08;如 height: 300px&#xff09;。 • 示例&#xff1a; css .cont…...

SpringBoot整合LogStash,LogStash采集服务器日志

LogStash 1. 下载 版本支持兼容表https://www.elastic.co/cn/support/matrix 版本: 7.16.x 的最后一个版本 https://www.elastic.co/downloads/past-releases/logstash-7-16-3 需要提前安装好jdk1.8和ES, 此处不在演示 2. 安装 tar -xvf logstash-7.16.3-linux-x86_64.tar.gz…...

LLM - 推理大语言模型 DeepSeek-R1 论文简读

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/146840732 免责声明:本文来源于个人知识与公开资料,仅用于学术交流,欢迎讨论,不支持转载。 DeepSeek-R1 通过强化学习,显著提升大语言模型推理能力,使用特殊的训…...

目前市场上,好用的校招系统是哪个?

在数字化浪潮的推动下&#xff0c;校园招聘已从传统的“海投简历线下宣讲”模式全面转向智能化、数据化。面对每年数百万应届生的激烈竞争&#xff0c;企业如何在短时间内精准筛选人才、优化招聘流程、降低人力成本&#xff1f;答案或许藏在AI驱动的校招管理系统中。而在这场技…...

Oracle logminer详解

Oracle LogMiner 是 Oracle 数据库提供的一个内置工具&#xff0c;用于分析和挖掘数据库的在线重做日志文件&#xff08;Online Redo Log Files&#xff09;​和归档日志文件&#xff08;Archive Log Files&#xff09;​。通过 LogMiner&#xff0c;用户可以查看数据库的历史操…...

SharpBrowser:用C#打造超快的个性化开源浏览器!

推荐一个基于.Net 8 和 CefSharp开发的开源浏览器。 01 项目简介 SharpBrowser 是一个用 C# 和 CefSharp 开发的全功能网页浏览器。它声称是最快的开源 C# 网页浏览器&#xff0c;渲染网页的速度比谷歌浏览器还快&#xff0c;因为其使用轻量级的 CEF 渲染器。 经过比较所有可…...

【企业级Web应用中的文件下载处理:从S3预签名URL到压缩状态管理】

企业级Web应用中的文件下载处理&#xff1a;从S3预签名URL到压缩状态管理 1. 引言&#xff1a;一个看似简单的下载功能背后 在开发企业级Web应用时&#xff0c;文件下载功能看似简单&#xff0c;却常常隐藏着诸多技术挑战。近期&#xff0c;我们在一个xx申报系统项目中&#…...

【新模型速递】PAI一键云上零门槛部署DeepSeek-V3-0324、Qwen2.5-VL-32B

DeepSeek近期推出了“DeepSeek-V3-0324”版本&#xff0c;据测试在数学推理和前端开发方面的表现已优于 Claude 3.5 和 Claude 3.7 Sonnet。 阿里也推出了多模态大模型Qwen2.5-VL的新版本--“Qwen2.5-VL-32B-Instruct”&#xff0c;32B参数量实现72B级性能&#xff0c;通杀图文…...

[原创](Modern C++)现代C++的关键性概念: 如何利用多维数组的指针安全地遍历所有元素

[作者] 常用网名: 猪头三 出生日期: 1981.XX.XX 企鹅交流: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共24年] 职业生涯: 22年 开发语言: C/C、80x86ASM、Object Pascal、Objective-C、C#、R、Python、PHP、Perl、 开发工具: Visual Studio、Delphi、XCode、C …...

flask开发中设置Flask SQLAlchemy 的 db.Column 只存储非负整数(即 0 或正整数)

如果你想控制一个 Flask SQLAlchemy 的 db.Column 只存储非负整数&#xff08;即 0 或正整数&#xff09;&#xff0c;你可以在模型中使用验证来确保这一点。一种常见的方法是使用模型的 validate 方法或者在执行插入或更新操作时进行检查。 以下是实现这一目标的几种方法&…...

【Elasticsearch基础】基本核心概念介绍

Elasticsearch作为当前最流行的分布式搜索和分析引擎&#xff0c;其强大的功能背后是一套精心设计的核心概念体系。本文将深入解析Elasticsearch的五大核心概念&#xff0c;帮助开发者构建坚实的技术基础&#xff0c;并为高效使用ES提供理论支撑。 1 索引&#xff08;Index&…...

Github 热点项目 awesome-mcp-servers MCP 服务器合集,3分钟实现AI模型自由操控万物!

【今日推荐】超强AI工具库"awesome-mcp-servers"星数破万&#xff01; ① 百宝箱式服务模块&#xff1a;AI能直接操作浏览器、读文件、连数据库&#xff0c;比如让AI助手自动整理Excel表格&#xff0c;三分钟搞定全天报表&#xff1b; ② 跨领域实战利器&#xff1a;…...

SpringMVC 拦截器(Interceptor)

一.拦截器 假设有这么一个场景&#xff0c;一个系统需要用户登录才能进入&#xff0c;在检验完用户的信息后对页面进行了跳转。但是如果我们直接输入跳转的url&#xff0c;可以绕过用户信息校验&#xff08;用户登录&#xff09;&#xff0c;直接进入系统。 因此我们引入了使…...

【NLP】16. NLP推理方法重点回顾 -- 52道多选题

Which of the following problems are commonly solved using sequence tagging? A) Named Entity Recognition (NER) B) Part-of-Speech (POS) Tagging C) Word Embedding Training D) Syntactic Dependency Parsing 序列标注是一种 NLP 任务&#xff0c;常用于 命名实体…...

Redisson分布式锁深度解析:原理与实现机制

Redisson作为Redis Java客户端中的分布式解决方案佼佼者&#xff0c;其分布式锁实现被广泛应用于生产环境。以下从底层设计到源码实现进行全面剖析。 一、核心架构设计 1. 整体架构图 graph LRA[客户端] --> B[RLock接口]B --> C[RedissonLock]C --> D[Redis命令执…...

Linux 系统调用实现机制详解

Linux 系统调用实现机制详解 —— fork()、execve()、waitpid() 内核层面的秘密 在 Linux 内核中&#xff0c;fork()、execve() 和 waitpid() 是构建多任务操作系统的三大基石&#xff0c;它们涉及进程控制、内存管理、文件系统等多个子系统。本文将带你一探它们在 内核层面的…...

责任链模式_行为型_GOF23

责任链模式 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为型设计模式&#xff0c;核心思想是将多个处理请求的对象连成一条链&#xff0c;请求沿链传递直到被处理。它像现实中的“多级审批流程”——请假或报销时&#xff0c;申请会逐级提交给…...

03-SpringBoot3入门-配置文件(自定义配置及读取)

1、自定义配置 # 自定义配置 zbj:user:username: rootpassword: 123456# 自定义集合gfs:- a- b- c2、读取 1&#xff09;User类 package com.sgu.pojo;import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.spring…...

学习记录-软件测试基础

一、软件测试分类 1.按阶段&#xff1a;单元测试&#xff08;一般开发自测&#xff09;、集成测试、系统测试、验收测试 2.按代码可见度测试&#xff1a;黑盒测试、灰盒测试、白盒测试 3.其他&#xff1a;冒烟测试(冒烟测试主要是在开发提测后进行&#xff0c;主要是测试主流…...

【蓝桥杯每日一题】3.28

&#x1f3dd;️专栏&#xff1a; 【蓝桥杯备篇】 &#x1f305;主页&#xff1a; f狐o狸x "今天熬的夜&#xff0c;会变成明天奖状的闪光点&#xff01;" 目录 一、唯一的雪花 题目链接 题目描述 解题思路 解题代码 二、逛画展 题目链接 题目描述 解题思路 解题代…...