面试官:你是怎么理解缓存的?
共 4888字,需浏览 10分钟
·
2020-11-23 17:27
本文公众号来源:IT人的职场进阶
作者:张勇
下面我结合自己使用缓存的历程,谈谈我对缓存的认识。
01 本地缓存
1. 页面级缓存
"foobar"
some jsp content
2. 对象缓存
3. 刷新策略
2018年,我和我的小伙伴自研了配置中心,为了让客户端以最快的速度读取配置, 本地缓存使用了 Guava,整体架构如下图所示:
那本地缓存是如何更新的呢?有两种机制:
客户端启动定时任务,从配置中心拉取数据。 当配置中心有数据变化时,主动推送给客户端。这里我并没有使用websocket,而是使用了 RocketMQ Remoting 通讯框架。
▍zookeeper watch机制
▍websocket 机制
websocket 和 zookeeper 机制有点类似,当网关与 admin 首次建立好 websocket 连接时,admin 会推送一次全量数据,后续如果配置数据发生变更,则将增量数据通过 websocket 主动推送给 soul-web。
http请求到达服务端后,并不是马上响应,而是利用 Servlet 3.0 的异步机制响应数据。当配置发生变化时,服务端会挨个移除队列中的长轮询请求,告知是哪个 Group 的数据发生了变更,网关收到响应后,再次请求该 Group 的配置数据。
pull 模式必不可少 增量推送大同小异
02 分布式缓存
1. 合理控制对象大小及读取策略
1、数据格式非常精简,只返回给前端必要的数据,部分数据通过数组的方式返回
2、使用 websocket,进入页面后推送全量数据,数据发生变化推送增量数据
再回到我的问题上,最终是用什么方案解决的呢?当时,我们的比分直播模块缓存格式是 JSON 数组,每个数组元素包含 20 多个键值对, 下面的 JSON 示例我仅仅列了其中 4 个属性。
[{
"playId":"2399",
"guestTeamName":"小牛",
"hostTeamName":"湖人",
"europe":"123"
}]
这种数据结构,一般情况下没有什么问题。但是当字段数多达 20 多个,而且每天的比赛场次非常多时,在高并发的请求下其实很容易引发问题。
基于工期以及风险考虑,最终我们采用了比较保守的优化方案:
[["2399","小牛","湖人","123"]]
修改完成之后, 缓存的大小从平均 300k 左右降为 80k 左右,YGC 频率下降很明显,同时页面响应也变快了很多。
但过了一会,cpu load 会在瞬间波动得比较高。可见,虽然我们减少了缓存大小,但是读取大对象依然对系统资源是极大的损耗,导致 Full GC 的频率也不低。
3)为了彻底解决这个问题,我们使用了更精细化的缓存读取策略。
我们把缓存拆成两个部分,第一部分是全量数据,第二部分是增量数据(数据量很小)。页面第一次请求拉取全量数据,当比分有变化的时候,通过 websocket 推送增量数据。
第 3 步完成后,页面的访问速度极快,服务器的资源使用也很少,优化的效果非常优异。
2. 分页列表查询
select id from blogs limit 0,10
select id from blogs where id in (noHitId1, noHitId2)
本地缓存:性能极高,for 循环即可 memcached:使用 mget 命令 Redis:若缓存对象结构简单,使用 mget 、hmget命令;若结构复杂,可以考虑使用 pipleline,lua脚本模式
03 多级缓存
缓存读取流程如下:
1、业务网关刚启动时,本地缓存没有数据,读取 Redis 缓存,如果 Redis 缓存也没数据,则通过 RPC 调用导购服务读取数据,然后再将数据写入本地缓存和 Redis 中;若 Redis 缓存不为空,则将缓存数据写入本地缓存中。
2、由于步骤1已经对本地缓存预热,后续请求直接读取本地缓存,返回给用户端。
3、Guava 配置了 refresh 机制,每隔一段时间会调用自定义 LoadingCache 线程池(5个最大线程,5个核心线程)去导购服务同步数据到本地缓存和 Redis 中。
优化后,性能表现很好,平均耗时在 5ms 左右。最开始我以为出现问题的几率很小,可是有一天晚上,突然发现 app 端首页显示的数据时而相同,时而不同。
1、惰性加载仍然可能造成多台机器的数据不一致
2、 LoadingCache 线程池数量配置的不太合理, 导致了线程堆积
缓存是非常重要的一个技术手段。如果能从原理到实践,不断深入地去掌握它,这应该是技术人员最享受的事情。
我想我更应该和朋友交流的是: 如何体系化的学习一门新技术。
选择该技术的经典书籍,理解基础概念 建立该技术的知识脉络 知行合一,在生产环境中实践或者自己造轮子 不断复盘,思考是否有更优的方案
新用户一年只需84.97元,我当年认证学生,以学生的身份购买都得10块钱一个月,现在一个月只要7块钱!
通过我的链接或者扫描二维码购买即可享受优惠:
https://www.aliyun.com/1111/pintuan-share?ptCode=MTk2NjQwOTYyMDkyNzI4MXx8MTE0fDE%3D&userCode=pfn5xpli
老实说我在学生时期就没折腾过虚拟机,直接上的云服务器,这给我在学习的时候省了不少的时间。现在一个月7块钱就可以拥有自己的一台服务器,如果还没买过的同学可以买起来~ 新人拥有自己的一台服务器可以先简单做些小事情(必经的一个过程):
学习Linux命令
部署Java环境(包括Elasticseach,Redis..等等),这些框架都是在Linux部署很方便,在Windows上安装就比较麻烦了。
把自己写的小东西挂在服务器
我写了非常详细的搭建教程,买了如果还不会用,联系我手把手教学!
如果不是新用户,可以用爸妈手机注册一个(我就是这样干的),享受阿里云的最低价!
【 阅读原文 】 购买最便宜的服务器