缓存穿透/击穿/雪崩(附生产BUG)

优质博文:IT-BLOG-CN

一、背景

为什么要写这篇文章?
生产缓存生成服务转java时,需要通过配置文件进行流量切换。开发人员同时打开了两个配置页面。原配置信息=ABCDEF。在第一个配置页面进行缓存切换,添加G业务缓存,配置信息=ABCDEFG。随后H业务也需要进行缓存切换,但开发人员在第二个配置页面添加了H,配置信息=ABCDEFH导致第一次添加的G业务写缓存丢失。随着时间的推移8分钟后G业务缓存陆续过期,造成缓存雪崩

为什么保存配置和审核配置的时候没有发现异常
切流量设计10多种业务需要修改20多次配置,操作上惯性认为页面刷入是最新的版本,没有逐一进行检查。

监控为什么没有及时告警
监控比较滞后,目前监控的指标比较粗粒度,只有缓存过期后,导致订单量下降才会进行告警。同时缓存命令率的监控也是10分钟后直接掉至0

影响的单量
影响订单300单,并立即回滚配置信息。

二、缓存雪崩

大量的key设置了相同的过期时间,或者因为Redis实例宕机,在同一时刻缓存全部失效,造成请求全部穿透到DB,瞬时DB请求量大、压力骤增,可能导致DB被打挂。

解决方案:
【1】过期时间打散: 避免大量key同时过期,可以在设置过期时间时,在基础过期时间上加一个随机值来打散过期时间,通过打散过期时间,避免同一时间大量缓存过期。
【2】不过期: 不为数据设置过期时间或者设置比较长的过期时间,由专门的job应用定时刷新缓存。
【3】Redis高可用: 通过主从复制,故障转移等高可用机制避免 Redis 集群不可用导致的缓存雪崩。
【4】数据库限流与熔断: 对数据库的读添加限流与熔断机制,目的主要是为了在无可避免的缓存雪崩时保护数据库,使得之后能快速恢复缓存。
【5】数据库解耦: 应用完全与数据库解耦,只读Redis,由专门的job应用主动填充缓存。

三、缓存穿透

访问一个缓存和数据库都不存在的key,此时会直接打到数据库上,并且因为查不到数据,也不会写入缓存,所以下一次同样会打到数据库上,请求每次都会走到数据库,流量大时可能导致数据库被打挂。

解决方案:
【1】空值缓存: 查询数据库发现没有数据,给对应的key存入一个空值缓存,代表数据库中没有数据,应用查询到空值就直接返回,避免了穿透到DB的读流量。
【2】布隆过滤器:
    1、空值缓存已经能解决问题,但是在数据量非常大的情况下,我们还得考虑空间利用的高效。
    2、布隆过滤器是这样一个数据结构,它有一个初始值为0bit数组以及Nhash函数构成,它可以快速判断或标记当前值是否存在,标记的主要步骤为三个:
         ☑️ 使用Nhash函数计算的Nhash值。
         ☑️ Nhash值与bit数组取模得到N个映射的下标。
         ☑️ 将bit数组中N个下标对应的位置置为1
    3、当我们需要查询一个值时,重复上述步骤1,2得到N个下标,当这N个下标上对应的值均为1,则说明该值已被标记,否则未被标记。
    4、当然由于存在hash冲突,会存在一定的误判,所以布隆过滤器的特点是判断不存在的,则一定不存在;判断存在的,大概率存在。以存在误判的代价,换取空间利用上的高效。
【3】非法值校验: 对于一些请求参数,我们是能够判断出是否合法,如果不合法直接在入口处拦截,自然不需要穿透到DB。比如机票查询请求了一个不存在的航线,我们可以在入口校验时将该请求拦截。

四、缓存击穿

存在一个高并发读的热点key,在缓存过期的一瞬间,有大量的读请求,由于此时缓存过期了,所以请求最终都会走到数据库,造成瞬时数据库请求量大、压力骤增,可能导致数据库被打挂。

解决方案:
【1】锁:
    1、当大量请求并发读取缓存并失败时,其实只需要一个线程/机器去访问数据库并填充缓存,其他线程/机器只需等待缓存填充完成后读取缓存就行。
    2、我们可以通过互斥锁使得只有一个线程/机器能够访问数据库并填充缓存,线程间的同步比较容易,因为是在一个进程内,使用java提供的同步机制,比如ReentrantLock即可。
    3、机器间的同步,由于涉及到分布式环境,因此需要分布式锁来进行同步。简单的分布式锁可以通过Redis或者DB实现,更高级的可以通过zookeeper这样的分布式协调服务来实现。

【2】热点数据不过期: 既然缓存击穿是由热点key过期导致的,那么我们可以不为热点数据设置过期时间,而是由专门的后台job应用进行定时的刷新,在携程内部qshcedule能很好的解决我们的需求。

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

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

相关文章

Java - Spring 表达式语言 (SpEL) 简单入门

Java - Spring 表达式语言 (SpEL) 简单入门 文章目录 Java - Spring 表达式语言 (SpEL) 简单入门引言一、环境二、资料三、引用SpEL依赖四、SeEL支持的功能基础1:获取对象值基础2:获取对象值基础3:集合对象象的访问基础4:使用SeEL…

各种排序方法总结

目录 1. 冒泡排序 (Bubble Sort 2. 选择排序 (Selection Sort) 3. 插入排序 (Insertion Sort) 4. 快速排序 (Quick Sort) 5. 归并排序 (Merge Sort) 6. 堆排序 (Heap Sort) 排序算法 时间复杂度 空间复杂度 备注冒泡排序 最好情况: O(n) 平均情况: O(n^2) 最坏情况: O(n^…

制冷压缩机液击介绍

液态制冷剂或润滑油随气体吸入压缩机气缸时损坏吸气阀片的现象,以及进入气缸后没有在排气过程迅速排出,在活塞接近上止点时,被压缩而产生的瞬间高液压的现象通常被称为液击。液击可以在很短时间内造成压缩受力件 ( 如阀片、活塞、连杆、曲轴、活塞销等 )的损坏,是往复式压…

Linux:linux系统中目录的遍历

Linux系统中目录的遍历 1、Linux中目录的遍历(1)函数opendir(2)函数readdir(3)函数closedir(4)遍历指定目录的所有文件和子目录 1、Linux中目录的遍历 (1)函数opendir 打开需要被遍历的目录 DIR *opendir(const char *pathname);pathname:待遍历的目录return&#…

国际期货收费行情源CTP推送式/期货配资软件开发对接行情源的技术性说明

在现代金融市场中,期货交易因其高风险和高回报特性而备受关注。为了满足期货交易者的需求,开发高效、稳定和安全的期货交易软件变得尤为重要。本文将对国际期货收费行情源CTP推送式及期货配资软件的开发对接行情源的技术细节进行详细说明。 一、CTP&…

Sequelize 提示报错ERR_HTTP_HEADERS_SENT

ERR_HTTP_HEADERS_SENT 是一个在 Node.js 环境中常见的错误,它通常发生在尝试向一个已经发送了 HTTP 头部的响应对象发送更多头部或数据时。在 Sequelize(一个基于 promise 的 Node.js ORM,用于 Postgres, MySQL, MariaDB, SQLite 和 Microsoft SQL Server 数据库)的上下文…

AJAX——express框架

本文分享到此结束,欢迎大家评论区相互讨论学习,接下来我们将用一个案例来接着学习AJAX的内容,下一篇给大家准备一个案例的准备工作分享。

Android studio中排除文件功能的小总结

刚开始发现android studio的sourceSets的main下面java的excludes无效,改了好多次都没成功,以为关键字不支持,或者是gradle版本问题,结果查了半天没成功。后来经过对比发现是相对路径问题。 在此总结一下,希望节省大家…

本地连接linux服务器上的sqlite数据库

要从本地机器连接到 Linux 服务器上的 SQLite 数据库文件,你需要采取以下步骤: 确保你有权限访问 Linux 服务器。 使用 SSH 隧道将本地端口转发到远程服务器。这允许你通过加密连接安全地访问远程数据库。 在本地机器上使用 SQLite 客户端或编程语言来…

过拟合和欠拟合小解

过拟合(Overfitting)和欠拟合(Underfitting)是机器学习领域中常见的两种问题,它们分别代表模型在训练数据和测试数据上表现不佳的两种极端情况。 过拟合(Overfitting) 过拟合是指模型在训练数…

微知-如何临时设置服务器风扇转速?(ipmitool raw 0x30 0x30 0x02 0xff 0x40)

服务器风扇可以通过PWM输出来控制转速。 设置方式 设置单次PWM ipmitool raw 0x30 0x30 0x02 0xff 0x40如果要持续设置需要类似while循环持续输出: while true; do ipmitool raw 0x30 0x30 0x02 0xff 0x64; done > /dev/null参数说明: 其他参数&a…

ClaimsettlementController

目录 1、 ClaimsettlementController 1.1、 保存三包表 1.2、 审核预约单 1.3、 反审核预约单 ClaimsettlementController using QXQPS.Models; using QXQPS.Vo; using System; using System.Collections; using System.Collections.Generic; using System.Linq…

云原生后端开发指南:拥抱未来的可扩展架构

云原生后端开发指南:拥抱未来的可扩展架构 随着企业数字化转型的深入,传统的IT架构正在向云原生架构迁移。云原生是一种充分利用云计算交付模式的方法,结合微服务、容器化和DevOps,帮助企业构建灵活、可扩展和高效的系统。在这篇…

【java】数组(超详细总结)

目录 一.一维数组的定义 1.创建数组 2.初始化数组 二.数组的使用 1.访问数组 2.遍历数组 3.修改数据内容 三.有关数组方法的使用 1.toString 2. copyOf 四.查找数组中的元素 1.顺序查找 2.二分查找binarySearch 五.数组排序 1.冒泡排序 2.排序方法sort 六.数组逆置…

科研绘图系列:R语言突出强调部分的饼图(pie plot)

文章目录 介绍加载R包数据数据预处理画饼图画图例合并图形系统信息介绍 饼图(Pie Chart),也称为圆图(Circle Graph),是一种圆形的统计图表,通过将圆分成若干扇形来展示数据的比例关系。每个扇形的角度大小代表了相应数据在总量中的占比。饼图的特点包括: 比例展示:直…

Redis知识应用索引指南

Redis,全称为Remote Dictionary Server,是一个开源的高性能键值对数据库。它以其卓越的性能、丰富的数据结构和灵活的持久化机制,在现代应用中扮演着至关重要的角色 1 什么是redis Redis是一个使用ANSI C语言编写的开源、跨平台的键值存储系…

10用户管理(Vue3+Spring Boot)

目录 1. 功能描述2. 接口地址3.后台Java代码4.前端框架搭建:views/user添加UserManageVue组件5. api/user.js中写请求接口代码6 获取用户信息7 删除用户8 修改状态9 效果演示 1. 功能描述 用户管理界面,对用户进行查询、状态变更、删除。2. 接口地址 #…

Linux系统——lvm逻辑卷

Linux系统——lvm逻辑卷 一、lvm逻辑卷1、lvm操作流程2、操作指令 二、逻辑卷操作1、创建逻辑卷1.1 /dev/cloud/openstack 5G xfs /cloud/openstack1.2 /dev/cloud/docker 10G ext4 /cloud/docker 2、逻辑卷扩容2.1 扩容流程2.2 需求一:扩容ext4文件系统的逻辑卷2.3…

Ubuntu-Ubuntu22.04下Anacodna3的qmake和Qt的qmake冲突问题

Ubuntu22.04下Anacodna3的qmake和Qt的qmake冲突问题 一、问题描述二、原因分析三、解决办法 一、问题描述 Ubuntu22.04下Anacodna3的qmake和Qt的qmake冲突问题 zhyzhy-HP:~/Sources/mpv-examples/libmpv/qt$ make g -c -pipe -g -Wall -Wextra -D_REENTRANT -fPIC -DQT_WIDGET…

TypeScript中 interface接口 type关键字 enum枚举类型

type interface总是傻傻分不清~~~ Type Aliases (type) type 关键字用于为类型定义一个别名。这可以是基本类型、联合类型、元组、数组、函数等。type 定义的类型在编译后的 JavaScript 代码中会被移除,不会留下任何运行时的代码。 //联合类型 type StringOrNumbe…