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

后端程序员常犯的错误-本地缓存相关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集成本地缓存基本常识&#xff1a; SpringBoot集成本地缓存性能之王Caffeine示例详解 SpringBoot 缓存之 Cacheable介绍 2 线上问题 2.1 发现过程 接口内的rpc调用报错&#xff0c;error级别的日志被监控平台报警。 2.2 故障排查 2.2.1 代码 Cacheable(cach…...

【收集表单数据】

07 【收集表单数据】 在 React 里&#xff0c;HTML 表单元素的工作方式和其他的 DOM 元素有些不同&#xff0c;这是因为表单元素通常会保持一些内部的 state。例如这个纯 HTML 表单只接受一个名称&#xff1a; <form><label>名字:<input type"text"…...

【前端面试】九、框架

目录 1 Vue2 实现方式 2 Vue3 实现方式 3 React 实现方式 4 Angular 实现方式 1 Vue2 实现方式 Vue2 是目前仍被广泛使用的前端框架之一&#xff0c;其特点包括响应式数据绑定、组件化开发等。 响应式系统&#xff1a;Vue2 使用 Object.defineProperty 来实现数据的响应式。…...

水泥电阻在电源电路中的作用

水泥电阻是将电阻线绕在无碱性耐热瓷件上&#xff0c;外面加上耐热、耐湿及耐腐蚀之材料保护固定并把绕线电阻体放入方形瓷器框内&#xff0c;用特殊不燃性耐热水泥充填密封而成。水泥电阻的外侧主要是陶瓷材质&#xff08;一般可分为高铝瓷和长石瓷&#xff09;。 水泥电阻器…...

报销管理软件怎么选?主流的10款对比

国内外排名前十的报销软件大对比&#xff1a;合思、Zoho Expense、金蝶财务报销系统、每刻报销、慧算账、Expensify、齐业成、汇联易、分贝通、QuickBooks Online。 在小型企业中&#xff0c;报销管理可能还可以由财务人员手工完成。然而&#xff0c;对于中到大型企业和快速发展…...

人工智能对就业产生怎样的影响?

在这个飞速发展的时代&#xff0c;人工智能&#xff08;AI&#xff09;如同一股不可阻挡的潮流&#xff0c;深刻地影响着我们的工作方式和生活模式。它既是技术革命的产物&#xff0c;也是推动社会进步的重要力量。然而&#xff0c;随着AI技术的普及和应用&#xff0c;关于其对…...

Vue Router 路由守卫详解

Vue Router 的路由守卫功能使我们能够在路由导航的不同阶段执行代码,提供了极大的灵活性和控制力。路由守卫可以帮助我们在用户导航到特定路由之前、之后或取消导航时执行逻辑,例如权限验证、数据获取或取消操作等。 路由守卫类型 Vue Router 提供了以下几种类型的路由守卫…...

Android 10.0 Launcher 启动流程

在前面SystemUI启动流程中说到&#xff0c;在SystemServer中会去启动各种系统服务&#xff0c;这里的launcher也是启动的其中一个服务ActivityManagerService去启动的。在android10之前&#xff0c;系统四大组件的启动都是在ActivityManagerService中&#xff0c;在android10中…...

OPenCV高级编程——OpenCV视频读写及录制技术详解

目录 引言 一、视频读取技术 VideoCapture 类 构造函数 常用方法 二、视频写入技术 VideoWriter 类 构造函数 常用方法 三、视频录制技术 1. 包含OpenCV头文件 2. 初始化VideoCapture对象 3. 设置视频编码器 4. 读取和写入视频帧 5. 释放资源 6. 编码格式选择 …...

jenkins获取sonarqube质量门禁结果

前景 在使用 Jenkins 集成 SonarQube 时&#xff0c;获取质量门禁&#xff08;Quality Gate&#xff09;结果非常重要。SonarQube 的质量门禁是一种质量控制机制&#xff0c;用于评估代码质量是否符合预设的标准。以下是获取质量门禁结果的意义和作用&#xff1a; 评估代码质量…...

【AI-12】浅显易懂地说一下损失函数

什么是损失函数&#xff1f; 咱们可以把损失函数想象成一个衡量你做的事情“好不好”的尺子。 比如说你在预测明天的天气&#xff0c;你给出的预测结果和实际的天气情况之间会有差别。损失函数就是用来计算这个差别有多大的。 如果你的预测结果和实际情况非常接近&#xff0c;…...

Python和java中super的使用用法(有点小语法上的差距,老忘就在这里置顶了)

文章目录 1 在 Java 中&#xff1a;2 在 Python 中&#xff1a; 在 Java 和 Python 中&#xff0c;子类调用父类方法的语法略有不同&#xff1a; 1 在 Java 中&#xff1a; 使用 super 关键字&#xff1a;在子类中&#xff0c;可以使用 super 关键字来调用父类的方法。super …...

在 QML 中使用 C++ 类和对象

1.实现 C 类&#xff0c;从 QObject 或 QObject 的派生类继承 类中第一行添加 Q_OBJECT 宏 2.修饰成员函数或属性 Q_INVOKABLE 宏用来定义可通过元对象系统访问的方法 Q_PROPERTY 宏用来定义可通过元对象系统访问的属性 信号或者槽&#xff0c;都可以直接在 QML 中访问 3. 在…...

什么是接口?

在前后端开发的语境中&#xff0c;接口&#xff08;Interface&#xff09;是一个非常重要的概念&#xff0c;它充当了前端&#xff08;通常是浏览器端或移动端应用&#xff09;与后端&#xff08;通常是服务器端的应用程序&#xff09;之间进行数据交换的桥梁。接口定义了双方交…...

传统自然语言处理(NLP)与大规模语言模型(LLM)详解

自然语言处理&#xff08;NLP&#xff09;和大规模语言模型&#xff08;LLM&#xff09;是理解和生成人类语言的两种主要方法。本文将介绍传统NLP和LLM的介绍、运行步骤以及它们之间的比较&#xff0c;帮助新手了解这两个领域的基础知识。 传统自然语言处理&#xff08;NLP&…...

实现Obsidian PC端和手机端(安卓)同步

步骤 1&#xff1a;在PC端设置Obsidian 安装Obsidian和Git&#xff1a;确保你的PC上已经安装了Obsidian和Git。你可以从Obsidian官网和Git官网下载并安装。 克隆GitHub代码库&#xff1a;在PC上打开命令行&#xff08;例如Windows的命令提示符或Mac/Linux的终端&#xff09;&a…...

基于大模型的 Agent 进行任务规划的10种方式

基于大模型的 Agent 基本组成应该包含规划&#xff08;planning)&#xff0c;工具&#xff08;Tools)&#xff0c;执行(Action)&#xff0c;和记忆(Memory)四个方面&#xff0c;本节将从 Agent 的概念、ReAct 框架、示例、以及一些论文思路来具体聊下任务规划的话题&#xff0c…...

计算机网络01

文章目录 浏览器输入URL后发生了什么&#xff1f;Linux 系统是如何收发网络包的&#xff1f;Linux 网络协议栈Linux 接收网络包的流程Linux 发送网络包的流程 浏览器输入URL后发生了什么&#xff1f; URL解析 当在浏览器中输入URL后&#xff0c;浏览器首先对拿到的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...

数据结构与算法-二分搜索树节点的查找

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、二分搜…...

C++|设计模式(七)|⭐️观察者模式与发布/订阅模式,你分得清楚吗

本文内容来源于B站&#xff1a; 【「观察者模式」与「发布/订阅模式」&#xff0c;你分得清楚吗&#xff1f;】 文章目录 观察者模式&#xff08;Observer Pattern&#xff09;的代码优化观察者模式 与 发布订阅模式 他们是一样的吗&#xff1f;发布订阅模式总结 我们想象这样一…...

计算机毕业设计选题推荐-学院教学工作量统计系统-Java/Python项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…...

人机交互不仅仅是科技问题

人机交互不仅仅局限于物理和数理科学的应用&#xff0c;还涉及到更广泛的管理、文理、哲学、艺术、伦理以及法律等领域。下面这些领域在人机协同和智能系统应用中扮演着重要角色&#xff1a; 智能系统在企业管理、资源分配、决策支持等方面的应用&#xff0c;可以帮助管理者优化…...

Lua Debug.GetInfo

在 Lua 中&#xff0c;debug.getinfo 函数的第一个参数指定了要获取信息的函数的级别。这个级别是一个整数&#xff0c;表示调用栈的深度。以下是一些常见的级别和它们的含义&#xff1a; - 1&#xff1a;当前函数&#xff08;即调用 debug.getinfo 的函数&#xff09;。 - 2&a…...

每日刷题(最短路、图论)

目录 游戏 思路 代码 魔法 思路 代码 P1364 医院设置 思路 代码 P1144 最短路计数 思路 代码 游戏 I-游戏_河南萌新联赛2024第&#xff08;三&#xff09;场&#xff1a;河南大学 (nowcoder.com) 思路 利用dijkstra去寻找起点到其余所有点的最短路径&#xff0c;当…...

远程服务器训练网络之tensorboard可视化

cd到tensorboard events存储的位置 启动tensorboard tensorboard --logdir./ 得到运行结果&#xff1a; TensorBoard 1.13.1 at http://work:6006 (Press CTRLC to quit) 创建tunnel映射到本地&#xff0c;在本地ssh&#xff0c;最好使用公网地址 ssh -N -L 8080:localhost:60…...

MySQL锁详解

锁是计算机在执行多线程或线程时用于并发访问同一共享资源时的同步机制&#xff0c;MySQL中的锁是在服务器层或者存储引擎层实现的&#xff0c;保证了数据访问的一致性与有效性。 MySQL锁&#xff1a; 按粒度分为&#xff1a;全局锁、表级锁、页级锁、行级锁。按模式分为&…...

面试问题记录:

1&#xff0c;hashmap扩容的时候&#xff0c;链表超长但不满足转变成红黑树的条件时&#xff1a; 【HashMap】链表和红黑树互相转换的几种情况和数组的扩容机制_hashmap红黑树转链表条件-CSDN博客 2&#xff0c;cglib与proxy区别 JDK 动态代理和 CGLIB 动态代理对比_动态代理…...

vue如何在组件中监听路由参数的变化

使用 watch 监听 $route 对象 的变化&#xff0c;从而捕捉路由参数的变化 beforeRouteUpdate 导航守卫 当前组件路由更新时调用 beforeRouteUpdate 钩子只在组件被复用时调用&#xff0c;即当组件实例仍然存在时。如果组件是完全重新创建的&#xff0c;那么应该使用 beforeR…...

徐州网站开发怎样/网络营销课程学什么

最近总有童鞋问&#xff0c;拿到的测序数据&#xff0c;我怎么知道或者评判质量好坏呢&#xff0c;别着急&#xff0c;今天给你推荐一款软件&#xff0c;让你轻松知道数据质量情况&#xff0c;它就是FastQC&#xff0c;它是高通量测序数据的高级质控工具&#xff0c;输入FastQ&…...

电子商务网站建设合同/搜索引擎优化方案

mockjs的简介&#xff1a; 使用mockjs可以事先模拟数据&#xff0c;前提是和后端约定好了数据接口&#xff0c;怎样的数据。使用mock就可以生成你要的数据了&#xff0c;从而实现开发时前后端分离。 其主要功能是&#xff1a; 基于数据模板生成模拟数据。 基于HTML模板生成模…...

mamp安装wordpress/建站 seo课程

一、windows安装不要安装旧的 boot2docker包&#xff0c;直接安装 DockerToolbox。 一路next&#xff0c;安装完成以后试用1、以管理员身份运行 docker quickstart terminal。docker version 因种种原因&#xff0c;重装了不下5次&#xff0c;终于成功了&#xff01; 二、cento…...

抚州建设网站/如何利用seo赚钱

文章目录文件上传和下载准备工作使用类介绍代码编写文件上传和下载 在Web应用中&#xff0c;文件上传和下载功能是非常常用的功能&#xff0c;这篇博客就来讲一下JavaWeb中的文件上传和下载功能的实现。 准备工作 对于文件上传&#xff0c;浏览器在上传的过程中是将文件以流…...

服务器怎样做网站呢/杭州疫情最新情况

参考链接 https://www.cnblogs.com/cxydczzl/archive/2018/08/30/9558294.html...

如何从网站获取图片做全景图/开鲁seo服务

X86寄存器 x86寄存器分类&#xff1a; 8个通用寄存器&#xff1a;EAX、EBX、ECX、EDX、ESI、EDI、ESP、EBP 1个标志寄存器&#xff1a;EFLAGS 6个段寄存器&#xff1a;CS、DS、ES、FS、GS、SS 5个控制寄存器&#xff1a;CR0、CR1、CR2、CR3、CR4 8个调试寄存器&#xff1a;DR0、…...