后端程序员常犯的错误-本地缓存相关bug和技术思考
1 springboot集成本地缓存基本常识:
SpringBoot集成本地缓存性能之王Caffeine示例详解
SpringBoot 缓存之 @Cacheable介绍
2 线上问题
2.1 发现过程
接口内的rpc调用报错,error级别的日志被监控平台报警。
2.2 故障排查
2.2.1 代码
@Cacheable(cacheManager = RedisKeyConstants.CACHE_MANAGER_LOCAL, value = RedisKeyConstants.Gpc.certificate.CACHE_NAME, key = RedisKeyConstants.Gpc.certificate.CACHE_KEY)
public User getData(Object obj) {User user = new User();try {Response<User> res = aliyunClient.doRpcCall(obj);if (!resp.getCode().equals("success!")) {log.error("error happening, code:{}, msg:{}", resp.getCode(), resp.getMsg());return null;}if (res.getData() == null) {log.error("error happening. rpc return a Null Object, code:{}, msg:{}", resp.getCode(), resp.getMsg());return null;}} catch (Exception e) {log.error("rpc调用异常", e);return user;}return user;
}
2.2.2 原因
(1)主要有两个,一个是当rpc调用异常的时候,会被try捕获并且直接return一个实例化的user对象,然后触发@Cacheable注解定义的本地缓存机制,导致异常调用的时候,对象也被缓存,随后直至本地缓存中该条目过期,后面的请求才会发起rpc请求更新缓存,所以对于rpc调用时获取的错误,应该不缓存。
(2)rpc调用成功但是返回了一个空对象,这个时候我直接返回的是null值,导致本地缓存没有存储这个空值,随后当流量走getData这个方法时,因为没有查到缓存,就会一直走rpc调用,造成cpu时间浪费,同时会延长响应时间,如果某一波大流量打进来,rpc服务甚至会挂掉,这个时候会发生缓存击穿。
3 解决
3.1 代码
@Cacheable(cacheManager = RedisKeyConstants.CACHE_MANAGER_LOCAL, value = RedisKeyConstants.Gpc.certificate.CACHE_NAME, key = RedisKeyConstants.Gpc.certificate.CACHE_KEY,unless = "#result==null")
public User getData(Object obj) {User user = new User();try {Response<User> res = aliyunClient.doRpcCall(obj);if (!resp.getCode().equals("success!")) {log.error("error happening, code:{}, msg:{}", resp.getCode(), resp.getMsg());return user;}if (res.getData() == null) {log.error("error happening. rpc return a Null Object, code:{}, msg:{}", resp.getCode(), resp.getMsg());return user;}} catch (Exception e) {log.error("rpc调用异常", e);return null;}user.setXXXX(res.getData().getXXXX());....return user;
}
3.2 解决方法
3.2.1 确保springboot不会缓存null值
在@Cacheable注解上添加unless = "#result==null"属性
3.2.2 try捕获异常时返回null(解决rpc异常仍然缓存的问题)
3.2.3 当rpc调用正常返回null或者有对象但没有实际存储值时返回user对象,以使得本地缓存这个实例化但是无值的user(解决缓存击穿问题)
3.3 测试过程
1 首先会在各个return之前会打印相关的error级别的日志以作观察
2 在rpc调用代码中故意写一个错误的url以使得出发异常或插入int i = 5/0触发异常,第一次调用触发rpc异常,然后第二次再进行,如果仍然触发异常或者执行了getData方法的代码,就说明异常后的返回值不会缓存。
3 模拟rpc调用返回空值,分两次调用,查看第二次是否会走getData方法,如果没走就说明缓存生效。
4 一些技术的其他思考【从阿里p8的聊天中得到的一些技术上的思考】
4.1 为什么对于rpc调用异常后的方法返回值不进行缓存?如果rpc故障时间长,每次都不缓存,是不是也存在缓存失效,长时间内数据都会进行rpc调用?【或者问不对rpc调用异常进行缓存的精确场景。】
(1)首先既然rpc异常了就不应该对null值进行缓存,后续的查询不能一直用null缓存。
(2)rpc是暂时故障,被调用方会进行迅速(秒级)的故障转移,比如重启、切换,在故障切换期间
4.2 如果rpc服务重启了,而本地缓存也刚好过期了,这个时候大流量过来同时调用这个rpc服务怎么办呢?
1. 异常降级处理
对于RPC服务,可以实现服务降级策略,当检测到RPC服务负载过高或出现异常时,可以临时返回一些兜底数据或执行简化的逻辑以减轻服务压力。
2. 限流
对于高频请求,尤其是批量操作导致的数据访问,可以通过限流策略来控制请求速率,避免短时间内对后端服务(包括缓存和RPC服务)造成过大压力。
3. 分布式锁
当缓存失效后,为了防止同时有大量对同一数据的访问请求打到后端服务,可以引入分布式锁的机制。在更新缓存前通过获取分布式锁来确保同一时间只有一个请求去调用RPC服务更新数据,并将结果写入缓存。其他的请求只需等待缓存更新即可获取数据,这种方式需要确保锁的获取与释放正确管理,以防止死锁或服务延迟。
相关文章:
后端程序员常犯的错误-本地缓存相关bug和技术思考
1 springboot集成本地缓存基本常识: SpringBoot集成本地缓存性能之王Caffeine示例详解 SpringBoot 缓存之 Cacheable介绍 2 线上问题 2.1 发现过程 接口内的rpc调用报错,error级别的日志被监控平台报警。 2.2 故障排查 2.2.1 代码 Cacheable(cach…...
【收集表单数据】
07 【收集表单数据】 在 React 里,HTML 表单元素的工作方式和其他的 DOM 元素有些不同,这是因为表单元素通常会保持一些内部的 state。例如这个纯 HTML 表单只接受一个名称: <form><label>名字:<input type"text"…...
【前端面试】九、框架
目录 1 Vue2 实现方式 2 Vue3 实现方式 3 React 实现方式 4 Angular 实现方式 1 Vue2 实现方式 Vue2 是目前仍被广泛使用的前端框架之一,其特点包括响应式数据绑定、组件化开发等。 响应式系统:Vue2 使用 Object.defineProperty 来实现数据的响应式。…...
水泥电阻在电源电路中的作用
水泥电阻是将电阻线绕在无碱性耐热瓷件上,外面加上耐热、耐湿及耐腐蚀之材料保护固定并把绕线电阻体放入方形瓷器框内,用特殊不燃性耐热水泥充填密封而成。水泥电阻的外侧主要是陶瓷材质(一般可分为高铝瓷和长石瓷)。 水泥电阻器…...
报销管理软件怎么选?主流的10款对比
国内外排名前十的报销软件大对比:合思、Zoho Expense、金蝶财务报销系统、每刻报销、慧算账、Expensify、齐业成、汇联易、分贝通、QuickBooks Online。 在小型企业中,报销管理可能还可以由财务人员手工完成。然而,对于中到大型企业和快速发展…...
人工智能对就业产生怎样的影响?
在这个飞速发展的时代,人工智能(AI)如同一股不可阻挡的潮流,深刻地影响着我们的工作方式和生活模式。它既是技术革命的产物,也是推动社会进步的重要力量。然而,随着AI技术的普及和应用,关于其对…...
Vue Router 路由守卫详解
Vue Router 的路由守卫功能使我们能够在路由导航的不同阶段执行代码,提供了极大的灵活性和控制力。路由守卫可以帮助我们在用户导航到特定路由之前、之后或取消导航时执行逻辑,例如权限验证、数据获取或取消操作等。 路由守卫类型 Vue Router 提供了以下几种类型的路由守卫…...
Android 10.0 Launcher 启动流程
在前面SystemUI启动流程中说到,在SystemServer中会去启动各种系统服务,这里的launcher也是启动的其中一个服务ActivityManagerService去启动的。在android10之前,系统四大组件的启动都是在ActivityManagerService中,在android10中…...
OPenCV高级编程——OpenCV视频读写及录制技术详解
目录 引言 一、视频读取技术 VideoCapture 类 构造函数 常用方法 二、视频写入技术 VideoWriter 类 构造函数 常用方法 三、视频录制技术 1. 包含OpenCV头文件 2. 初始化VideoCapture对象 3. 设置视频编码器 4. 读取和写入视频帧 5. 释放资源 6. 编码格式选择 …...
jenkins获取sonarqube质量门禁结果
前景 在使用 Jenkins 集成 SonarQube 时,获取质量门禁(Quality Gate)结果非常重要。SonarQube 的质量门禁是一种质量控制机制,用于评估代码质量是否符合预设的标准。以下是获取质量门禁结果的意义和作用: 评估代码质量…...
【AI-12】浅显易懂地说一下损失函数
什么是损失函数? 咱们可以把损失函数想象成一个衡量你做的事情“好不好”的尺子。 比如说你在预测明天的天气,你给出的预测结果和实际的天气情况之间会有差别。损失函数就是用来计算这个差别有多大的。 如果你的预测结果和实际情况非常接近,…...
Python和java中super的使用用法(有点小语法上的差距,老忘就在这里置顶了)
文章目录 1 在 Java 中:2 在 Python 中: 在 Java 和 Python 中,子类调用父类方法的语法略有不同: 1 在 Java 中: 使用 super 关键字:在子类中,可以使用 super 关键字来调用父类的方法。super …...
在 QML 中使用 C++ 类和对象
1.实现 C 类,从 QObject 或 QObject 的派生类继承 类中第一行添加 Q_OBJECT 宏 2.修饰成员函数或属性 Q_INVOKABLE 宏用来定义可通过元对象系统访问的方法 Q_PROPERTY 宏用来定义可通过元对象系统访问的属性 信号或者槽,都可以直接在 QML 中访问 3. 在…...
什么是接口?
在前后端开发的语境中,接口(Interface)是一个非常重要的概念,它充当了前端(通常是浏览器端或移动端应用)与后端(通常是服务器端的应用程序)之间进行数据交换的桥梁。接口定义了双方交…...
传统自然语言处理(NLP)与大规模语言模型(LLM)详解
自然语言处理(NLP)和大规模语言模型(LLM)是理解和生成人类语言的两种主要方法。本文将介绍传统NLP和LLM的介绍、运行步骤以及它们之间的比较,帮助新手了解这两个领域的基础知识。 传统自然语言处理(NLP&…...
实现Obsidian PC端和手机端(安卓)同步
步骤 1:在PC端设置Obsidian 安装Obsidian和Git:确保你的PC上已经安装了Obsidian和Git。你可以从Obsidian官网和Git官网下载并安装。 克隆GitHub代码库:在PC上打开命令行(例如Windows的命令提示符或Mac/Linux的终端)&a…...
基于大模型的 Agent 进行任务规划的10种方式
基于大模型的 Agent 基本组成应该包含规划(planning),工具(Tools),执行(Action),和记忆(Memory)四个方面,本节将从 Agent 的概念、ReAct 框架、示例、以及一些论文思路来具体聊下任务规划的话题,…...
计算机网络01
文章目录 浏览器输入URL后发生了什么?Linux 系统是如何收发网络包的?Linux 网络协议栈Linux 接收网络包的流程Linux 发送网络包的流程 浏览器输入URL后发生了什么? URL解析 当在浏览器中输入URL后,浏览器首先对拿到的URL进行识别…...
基于SpringBoot微服务架构下前后端分离的MVVM模型浅析
基于SpringBoot微服务架构下前后端分离的MVVM模型浅析 “A Brief Analysis of MVVM Model in Front-end and Back-end Separation based on Spring Boot Microservices Architecture” 完整下载链接:基于SpringBoot微服务架构下前后端分离的MVVM模型浅析 文章目录 基于Spring…...
44444444444
4444444444444444...
7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
