四种缓存的避坑总结

news2025/1/10 20:53:23

背景

分布式、缓存、异步和多线程被称为互联网开发的四大法宝。今天我总结一下项目开发中常接触的四种缓存实际项目中遇到过的问题。

JVM堆内缓存

JVM堆内缓存因为可以避免memcache、redis等集中式缓存网络通信故障问题,目前还在项目中广泛使用。

堆内缓存需要注意GC的问题。假如我们的设计是定时的从远程来拉取数据更新本地缓存。一定要注意两点:第一不要全量拉取覆盖,第二不要把一个大对象整体替换为新对象。

先说全量拉取覆盖。全量拉取会有很大的网络开销,会造成网络流量尖刺。有人说没事,我们带宽很足,内网访问,不怕不怕。但是稳定性需要修炼的一项是削峰填谷。让系统在平稳的环境中运行。不然,在拉取大缓存新数据的数据突然来了个突发流量?根据墨菲定律,凡是有几率会发生的事情就一定会发生。编程需谨慎。

再说大对象整体替换的问题,这会造成GC问题。伪代码如下:


List<POJO> oldList = initList();
public void refresh() {
      List<POJO> newList = dataFromNetworkService.getAll();
      oldList = new List();
      for(POJO pojo : newList) {
          oldList.add(pojo);
      }
}

如果从网上拉取的数据和在缓存里存储的数据,对象类型没有发生改变。引起的转换开销还稍微小点。因为比如对象POJO存在一个列表里。这个列表虽然很大,但是里面存的都是对象的引用。实际的POJO并没有发生变化。上面伪代码虽然新建一个list对象,遍历添加新对象比直接oldList=newList要傻些。但是遍历过程实际上pojo对象没有发生改变。所以这里影响GC的只是oldList这个对象(不包括从网络上拉取回来数据的过程)。

但是如果代码这样写:


List<POJO2> oldList = initList();
public void refresh() {
      List<POJO1> newList = dataFromNetworkService.getAll();
      oldList = new List();
      for(POJO2 pojo : newList) {
          oldList.add(Beanutils.copy(new POJO2(), pojo));
      }
}

遍历过程将会将原来的POJO1全部新建一遍,这些对象一般情况下全部先进入堆内存的新生代,再经过数次young gc后进入老年代。会造成GC频繁。

我所做过的项目,一般认为一天一到2次fullgc为合理值。这样,如果比如预先知道某个时间点有大促,可通过提前触发GC等方式避免高峰期爆发fullgc。younggc至少是5分钟一次,甚至更久触发认为是正常。这样可以通过控制避过秒杀等场景。

JVM堆外缓存

堆外缓存的内存回收原理使用的是Java的虚引用(参见《Java的强引用、软引用、弱引用、虚引用》)。这个设计可以避免JVM的GC问题,但是处理不好可能会造成更严重的后果:整个机器内存被打满,机器可能会挂掉。其实挂掉一台在一般企业的生产环境还好,因为一般都会有容灾的冗余机器。但是更常见的一种情况是机器忙于swap内存交换,机器活着但是响应很慢。属于半死不活。

这个问题我没在线上遇到过,但是我同事之前在超级大厂的时候遇到过。

有的同学说那我严格算好内存,做好监控。这里面要就要依赖人为的因素来做紧急处理。而人是稳定性中最不可靠的。因为问题通常不发生在人清醒、手里事情很少的时候。而是一种雪上加霜的存在。比如大促时,流量上来了,线程数会增多,每个线程都会申请线程栈资源,系统处理IO,这时候系统会申请更多的buffers/cached内存。

linux的buffers/cached

linux系统上运行一下top 命令或者free命令,都能够看到buffers和cached相关的数据。需要注意的是通常我们看到的监控数据 空闲内存百分比,并非是下面显示的free/total,而是(free+buffers+cached)/total

buffers在Linux系统中通常被作为与块存储的IO缓存使用。所谓块存储可简单理解为将数据直接写到裸磁盘。而cached则一般会用于文件系统的IO缓存。比如page cache这种内存换页功能。

听不明白也没关系,因为事实上它们两个经常配合使用。比如与磁盘交换数据、进行网络通信时都会用。buffers和cached是实实在在被操作系统的系统进程在使用的,但是如果用户进程需要可以很快释放。所以通常会将它算到剩余可用内存里。

但是这个也要注意了。比如在IO密集型的系统,如果buffers/cached被大幅占用,会降低IO速度,进而降低系统吞吐。甚至有可能一个请求几秒才能到达应用程序,造成请求超时。

集中式缓存

redis缓存其实也有本机代理,可以缓存一些活跃的数据在本机上,本机可以取到不数据时不需要跨网络通信。但是因为redis本质是key-value的结构。如果需要根据通配符取数据全量,如果网络出现故障,可能会影响数据的完整性。

但是redis缓存最让人担心的是不规范的使用方法。比如存一个很大的value。具体这个对网络和存储造成的问题就不详细说了。可以想象下马桶堵了的情景。

总结

贝尔实验室的面向对象编程专家Tom Cargill说:

最初90%的开发工作将会用去你最初90%的开发时间。剩下的10%的开发量将会用去你另外一个90%的开发时间。

我理解剩下10%占用了90%的时间是由于超出了原有知识贮备,需要临时抱佛脚,甚至需要拿着锤子找钉子造成的。所以或者也可以这样做:

每周持续投入5%的学习时间,10%的思考时间,再用100%的时间去完成100%的开发。

 

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

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

相关文章

FFmpeg5.0源码阅读——avformat_find_stream_info

摘要&#xff1a;在使用FFmpeg库时通常使用avformat_find_stream_info相关函数来探测流的基本信息&#xff0c;为了更加深入理解FFmpeg的基本流程&#xff0c;本文根据FFmpeg 5.0的源码详细描述了该函数的具体实现。   关键字&#xff1a;FFmpeg   读者须知&#xff1a;读者…

数学之美:神奇的杨辉三角形,比帕斯卡早了近600年,致敬中国古代数学家(63)

小朋友们好&#xff0c;大朋友们好&#xff01; 我是猫妹&#xff0c;一名爱上Python编程的小学生。 和猫妹学Python&#xff0c;一起趣味学编程。 今日主题 什么是杨辉三角形&#xff1f; 杨辉三角形有什么规律&#xff1f; 中国古代数学家杨辉。 西方科学家帕斯卡。 杨…

【开源与项目实战:开源实战】81 | 开源实战三(上):借Google Guava学习发现和开发通用功能模块

上几节课&#xff0c;我们拿 Unix 这个超级大型开源软件的开发作为引子&#xff0c;从代码设计编写和研发管理两个角度&#xff0c;讲了如何应对大型复杂项目的开发。接下来&#xff0c;我们再讲一下 Google 开源的 Java 开发库 Google Guava。 Google Guava 是一个非常成功、…

智能指针类模板:auto_ptr、unique_ptr、shared_ptr的原理与使用

1. 什么是智能指针 智能指针是行为类似于指针的类对象&#xff0c;通常用于管理动态内存分配。C程序通常手动动态分配堆内存&#xff0c;但如果动态分配的内存没有释放&#xff0c;则会发生内存泄漏。 例如代码段1.1。 // 代码段1.1 void demo() {double *pd new double;*pd…

使用STM32F103的串口实现IAP程序升级功能

使用STM32F103的串口实现IAP程序升级功能 &#x1f3ac;IAP程序烧录全过程演示&#xff1a; ✨这几天折腾IAP升级功能&#xff0c;狂补了很多相关BootLoader相关的知识。本来最想实现IAP升级程序的方式是&#xff0c;基于SPI通讯的SD卡&#xff0c;借助挂载的FatFS文件系统&am…

C++中的内存分区

目录 操作系统的内存区域 C内存分区模型 1. 程序运行前 2. 程序运行后 3. new 操作符的使用 操作系统的内存区域 text段&#xff1a;存储程序的二进制指令&#xff0c;即程序源码编译后的二进制代码data段&#xff1a;存储已被初始化的全局变量、常量bss段&#xff1a;存储…

ES-工作原理

前言 ​ 搜索引擎是对数据的检索&#xff0c;而数据总体分为两种&#xff1a;结构化数据和非结构化数据。而对于结构化数据&#xff0c;因为他们具有特定的结构&#xff0c;所以一般都是可以通过关系型数据库MySQL/oracle的二维表的方式存储和搜索&#xff0c;也可以建立索引。…

Redis的简单使用 (实现Session持久化)

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一、Redis数据类型的使用 1. 字符串&#xff…

Redis【入门篇】---- Redis的Java客户端-Jedis

Redis【入门篇】---- Redis的Java客户端-Jedis 1. Jedis快速入门2. Jedis连接池1. 创建Jedis连接池2. 改造原始代码 在Redis官网中提供了各种语言的客户端&#xff0c;地址&#xff1a;https://redis.io/docs/clients/ 其中Java客户端也包含很多&#xff1a; 标记为❤的就是推荐…

密码学证明方案寒武纪大爆发——扩容、透明性和隐私的变革潜力

1. 引言 前序博客有&#xff1a; ZKP大爆炸 本文主要参考&#xff1a; StarkWare 2023年6月博客 Cambrian Explosion of Cryptographic Proofs----The transformative potential for scalability, transparency, and privacy2023年3月Eli Ben-Sasson在The 13th BIU Winter …

JavaWeb之Cookie和Session

文章目录 CookieCookie基本介绍Cookie的基本使用Cookie的创建从服务器获取CookieCookie值的修改方案一方案二 浏览器查看CookieCookie声明控制Cookie有效路径Path的设置 SessionSession基本介绍Session的创建和获取&#xff08;id号&#xff0c;是否为新&#xff09;Session域数…

【SQL server关键字】

目录&#xff1a; 前言一、CREATE -- 创建二、INSERT INTO VALUES -- 插入数据三、SELECT FROM -- 查找数据1.SEKECT简单了解2.函数的使用3.选择列表与group by子句的对应4.exists子查询 四、UPDATE SET -- 更改数据五、ALTER -- 修改属性六、JOIN ON-- 链接多个表1. join初…

JDBC 望舒客栈项目 万字详解

目录 一、前言 二、项目结构 三、准备工作 1.建立子包 : 2.导入jar包 : 3.工具类 : 1 Utility工具类 2 JDBCUtilsDruid工具类 4.导入配置文件 : 5.引入BasicDAO : 四、项目主体 1.界面显示 : 1 代码演示 2 运行测试 2.用户登录 : 1 创建员工表employee 2 创建Ja…

JavaScript 事件加载有哪些应用场景?

&#x1f482; 个人网站:【海拥】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 目录 前言什么是JavaScript事…

VUE L MVVM模型 ③

目录 文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持✨ V u e j s Vuejs Vuejs M V V M MVVM MVVM模型Data与El的2种写法总结 文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持✨ ⡖⠒⠒⠒…

多线程中的wait和notify

1、wait和notify 由于线程之间是抢占式执行的&#xff0c;所以线程之间的执行先后顺序难以预知。但实际上是希望合理的协调多个线程之间的执行先后顺序。 完成这个协调工作&#xff0c;主要涉及到三个方法 *wait()/wait(long timeout);让当前线程进入等待状态。 *notify()/n…

【每日算法 数据结构(C++)】—— 02 | 数组的并交集(解题思路、流程图、代码片段)

文章目录 01 | &#x1f451; 题目描述02 | &#x1f50b; 解题思路交集并集 03 | &#x1f9e2; 代码片段交集并集 When you feel like giving up, remember why you started. 当你想放弃时&#xff0c;请记住为什么你开始 01 | &#x1f451; 题目描述 给你两个数组&#xff…

学习机组过程中的疑难问题与解决 -----(1)

本文章是在学习计算机组成原理过程中个人感觉需要理解与记忆的问题&#xff0c;还有一些在学习过程中自己产生的疑问以及解答,本文章可能排版不良&#xff0c;精力有限&#xff0c;还请见谅 第一章&#xff1a; &#xff08;1&#xff09;MAR的位数对应着存储单元的个数&#…