四种缓存的避坑总结!!图文并茂细致入微(建议收藏)

Posted king哥Java架构

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了四种缓存的避坑总结!!图文并茂细致入微(建议收藏)相关的知识,希望对你有一定的参考价值。

背景

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

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分钟一次,甚至更久触发认为是正常。这样可以通过控制避过秒杀等场景。

如果你觉得自己学习效率低,缺乏正确的指导,可以加入资源丰富,学习氛围浓厚的技术圈一起学习交流吧!
[Java架构群]
群内有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的JAVA交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。

**JVM堆外缓存
**

这个设计可以避免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%的开发。
一直想整理出一份完美的面试宝典,但是时间上一直腾不开,这套一千多道面试题宝典,结合今年金三银四各种大厂面试题,以及 GitHub 上 star 数超 30K+ 的文档整理出来的,我上传以后,毫无意外的短短半个小时点赞量就达到了 13k,说实话还是有点不可思议的。

一千道互联网 Java 工程师面试题

内容涵盖:Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、Redis、mysql、Spring、SpringBoot、SpringCloud、RabbitMQ、Kafka、Linux等技术栈(485页)

初级—中级—高级三个级别的大厂面试真题

阿里云——Java 实习生/初级

List 和 Set 的区别 HashSet 是如何保证不重复的

HashMap 是线程安全的吗,为什么不是线程安全的(最好画图说明多线程环境下不安全)?

HashMap 的扩容过程

HashMap 1.7 与 1.8 的 区别,说明 1.8 做了哪些优化,如何优化的?

对象的四种引用

Java 获取反射的三种方法

Java 反射机制

Arrays.sort 和 Collections.sort 实现原理 和区别

Cloneable 接口实现原理

异常分类以及处理机制

wait 和 sleep 的区别

数组在内存中如何分配

答案展示:

美团——Java 中级

BeanFactory 和 ApplicationContext 有什么区别

Spring Bean 的生命周期

Spring IOC 如何实现

说说 Spring AOP

Spring AOP 实现原理

动态代理(cglib 与 JDK)

Spring 事务实现方式

Spring 事务底层原理

如何自定义注解实现功能

Spring MVC 运行流程

Spring MVC 启动流程

Spring 的单例实现原理

Spring 框架中用到了哪些设计模式

为什么选择 Netty

说说业务中,Netty 的使用场景

原生的 NIO 在 JDK 1.7 版本存在 epoll bug

什么是 TCP 粘包/拆包

TCP 粘包/拆包的解决办法

Netty 线程模型

说说 Netty 的零拷贝

Netty 内部执行流程

答案展示:

蚂蚁金服——Java 高级

题 1:

  1. jdk1.7 到 jdk1.8 Map 发生了什么变化(底层)?

  2. ConcurrentHashMap

  3. 并行跟并发有什么区别?

  4. jdk1.7 到 jdk1.8 java 虚拟机发生了什么变化?

  5. 如果叫你自己设计一个中间件,你会如何设计?

  6. 什么是中间件?

  7. ThreadLock 用过没有,说说它的作用?

  8. Hashcode()和 equals()和==区别?

  9. mysql 数据库中,什么情况下设置了索引但无法使用?

  10. mysql 优化会不会,mycat 分库,垂直分库,水平分库?

  11. 分布式事务解决方案?

  12. sql 语句优化会不会,说出你知道的?

  13. mysql 的存储引擎了解过没有?

  14. 红黑树原理?

题 2:

  1. 说说三种分布式锁?

  2. redis 的实现原理?

  3. redis 数据结构,使⽤场景?

  4. redis 集群有哪⼏种?

  5. codis 原理?

  6. 是否熟悉⾦融业务?记账业务?蚂蚁⾦服对这部分有要求。

好啦~展示完毕,大概估摸一下自己是青铜还是王者呢?

前段时间,在和群友聊天时,把今年他们见到的一些不同类别的面试题整理了一番,于是有了以下面试题集,也一起分享给大家~

如果你觉得这些内容对你有帮助,可以加入csdn进阶交流群,领取资料

基础篇


JVM 篇


MySQL 篇



Redis 篇




由于篇幅限制,详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!

需要的小伙伴,可以一键三连,下方获取免费领取方式!
在这里插入图片描述

以上是关于四种缓存的避坑总结!!图文并茂细致入微(建议收藏)的主要内容,如果未能解决你的问题,请参考以下文章

分享 15 个 Vue3 全家桶开发的避坑经验

❤️吐血总结《MySQL从入门到成神》,图文并茂(建议收藏)❤️

❤️吐血总结《Mysql从入门到入魔》,图文并茂(建议收藏)❤️

Java 工程师必读的避坑宝典

Java 工程师必读的避坑宝典

从单体迈向 Serverless 的避坑指南