4.1 缓存的使用判断
什么时候使用缓存的判断其实比较简单,抓住两点就行了:
1、是不是热点数据?
所谓热点,一般是遵循二八定律,即百分之八十的访问集中在百分之二十的数据上。
2、是不是读比写多?
这个比例一般为2:1。
4.2 什么时候不应该使用缓存?
反过来就是了。
1、没有热点数据不要使用缓存,也没什么意义。
因为内存资源是比较宝贵的。
2、频繁修改的数据不要使用缓存。
因为可能写入后还来不及读取就已失效或被淘汰,并且容易产生脏读。
4.3 合理使用缓存
最后,最重要的是确认是否需要使用缓存?
确定了后,再选择合适的缓存工具及使用缓存的方式。
5. 缓存时常见的一些问题
使用缓存优点很多,但也存在一些很常见的问题。双刃之剑,就看怎么用了。
列举一些我们工作中常见的一些缓存问题,并给出至少一种解决方案。
5.1 缓存更新带来的数据不一致与脏读
缓存更新的常见策略有:
1、先更新数据库再更新缓存;
2、先更新数据库再删除缓存;
3、先删除缓存再更新数据库;
4、定时清理缓存;
5、有请求访问数据时,判断缓存是否过期,过期从数据库中刷新缓存。
在这几种方案中,如果修改缓存与数据库不在同一个事物中,就带来了数据不一致和脏读的问题。
对应方案1:先删除缓存再更新数据库,并且在同一个事物中。
对应方案2:缓存自动失效后,另外的异步线程进行缓存更新。
对应方案3:缓存更新在并发、分布式要考虑锁,redis天生就是单线程,比较有优势。
5.2 怎么做缓存预热
缓存预热是指在用户可访问服务之前,将热点数据加载到缓存的操作,这样可以有效避免上线后瞬时大流量造成系统不可用。
缓存预热的一般性策略:
1、开发个缓存刷新功能,手工刷新;
2、项目启动的时候自动进行加载(一般为字典表等数据量不大的数据);
3、设置个定时器,自动刷新缓存;
4、提前统计热点数据,事先批量加载到如redis这样缓存工具中。
5.3 缓存重建
缓存失效后,重建热点缓存,如果耗时较长,在重建过程中,性能、负载不好。
对应方案:
1、正常情况下,交错缓存失效时间,减轻缓存压力;
2、崩溃失效的情况下,可以使用带持久化功能的缓存来恢复,比如Redis;
3、如果是MongoDB则不太一样,它是采用mmap来将数据文件映射到内存中,所以当MongoDB重启时,这些映射的内存并不会清掉,不需要进行缓存重建与预热。
5.4 缓存雪崩与可用性
缓存雪崩:缓存在同一时间失效时,访问直达数据库层,可能导致DB挂掉、系统崩溃。
对应方案1:交错缓存失效时间或随机缓存失效时间。
对应方案2:主从热备(Redis Sentinel)。
对应方案3:集群/水平切分(Redis Cluster、一致性哈希)。
5.5 缓存穿透
缓存穿透:持续高并发访问某个不存在的Key。
对应方案1:空值缓存。
对应方案2:布隆过滤器(bloom filter) + bitmap。穷举可能访问的数据放入bitmap中,使用hash访问。
5.6 缓存击穿
缓存击穿:热点Key失效,高并发请求,直击数据库。
缓存击穿与缓存穿透很相似,不同点是是缓存击穿前访问的是真实的热点数据,只是在某一刹那失效了,造成了击穿的效果。
这样看,它其实也是缓存雪崩的一个特例。与雪崩的区别即在于击穿是对于特定的热点数据,而雪崩是全部数据。
对应方案:多级缓存及交错失效时间 + LRU 淘汰算法。
对于热点数据进行二级或多级缓存,并对于不同级别的缓存设定不同的失效时间,缓解雪崩。
此外可使用LRU的变种算法LRU-K缓存数据。
5.7 缓存降级
缓存降级是服务降级中的一环。
在访问量剧增,导致服务出现问题时,为了保证核心服务可用,防止发生缓存雪崩,可进行服务降级。
以redis为例,比较常见的做法就是,不去数据库查询,而是直接返回默认值给用户。
缓存降级也可根据日志级别进行预案设置。
6. 分布式缓存的选型
说了这么多缓存的原理与策略,说说我们在实际工作中应该怎么去做缓存选型。
以下就是常用的几种缓存工具。
6.1 Ehcache
Ehcache是纯Java开源的缓存框架,最早从hibernate发展而来,现在算是springboot中的官配缓存工具,整合简单。特点如下:
-
快速,针对大型高并发系统场景,Ehcache的多线程机制有相应的优化改善;
-
简单,很小的jar包,简单配置就可直接使用,单机场景下无需过多的其他服务依赖;
-
支持多种的缓存策略,灵活;
-
缓存数据有两级:内存和磁盘,与一般的本地内存缓存相比,有了磁盘的存储空间,将可以支持更大量的数据缓存需求;
-
具有缓存和缓存管理器的侦听接口,能更简单方便的进行缓存实例的监控管理;
-
支持多缓存管理器实例,以及一个实例的多个缓存区域。
6.2 Guava Cache
Guava Cache是Google开源的Java重用工具集库Guava里的一款缓存工具,特点如下:
-
自动将entry节点加载进缓存结构中;
-
当缓存的数据超过设置的最大值时,使用LRU算法移除;
-
具备根据entry节点上次被访问或者写入时间计算它的过期机制;
-
缓存的key被封装在WeakReference引用内;
-
缓存的Value被封装在WeakReference或SoftReference引用内;
-
统计缓存使用过程中命中率、异常率、未命中率等统计数据。
6.3 Memcache
memcache本身不支持分布式,是通过客户端的路由处理来达到分布式解决方案的目的。特点如下:
-
memcache使用预分配内存池的方式管理内存;
-
所有数据存储在物理内存里;
-
非阻塞IO复用模型,纯KV存取操作;
-
多线程,效率高,会遇到锁等上下文切换问题;
-
只支持简单KV数据类型;
-
数据不支持持久化。
6.4 Redis
Redis是当前主流的高性能内存数据库,多用于存储缓存数据,并能实现轻量级的MQ功能。特点如下:
- 临时申请空间,可能导致碎片;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
总结
对于面试还是要好好准备的,尤其是有些问题还是很容易挖坑的,例如你为什么离开现在的公司(你当然不应该抱怨现在的公司有哪些不好的地方,更多的应该表明自己想要寻找更好的发展机会,自己的一些现实因素,比如对于我而言是现在应聘的公司离自己的家更近,又或者是自己工作到达了迷茫期,想跳出迷茫期等等)
Java面试精选题、架构实战文档
整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~
你的支持,我的动力;祝各位前程似锦,offer不断!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
结
对于面试还是要好好准备的,尤其是有些问题还是很容易挖坑的,例如你为什么离开现在的公司(你当然不应该抱怨现在的公司有哪些不好的地方,更多的应该表明自己想要寻找更好的发展机会,自己的一些现实因素,比如对于我而言是现在应聘的公司离自己的家更近,又或者是自己工作到达了迷茫期,想跳出迷茫期等等)
[外链图片转存中…(img-zWkMD9yx-1713685770286)]
Java面试精选题、架构实战文档
整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~
你的支持,我的动力;祝各位前程似锦,offer不断!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!