网易首页 > 网易号 > 正文 申请入驻

面对本地缓存和分布式缓存,我们该如何选择?

0
分享至

对于应用系统来讲,我们经常将缓存划分为本地缓存和分布式缓存。

分布式缓存:和应用分离的缓存组件或服务,与本地应用隔离,多个应用可直接共享缓存。

一、缓存的本质

我们常常会讲:“加了缓存,我们的系统就会更快” 。

所谓的“更快”,本质上做到了如下两点:

减小 CPU 消耗

将原来需要实时计算的内容提前算好、把一些公用的数据进行复用,这可以减少 CPU 消耗,从而提升响应性能。

减小 I/O 消耗

假如可以通过增强 CPU、I/O 本身的性能来满足需求的话,升级硬件往往是更好的解决方案,即使需要一些额外的投入成本,也通常要优于引入缓存后可能带来的风险。

从开发角度来说,引入缓存会提高系统复杂度,因为你要考虑缓存的失效、更新、一致性等问题。

从运维角度来说,缓存会掩盖掉一些缺陷,让问题在更久的时间以后,出现在距离发生现场更远的位置上。

从安全角度来说,缓存可能泄漏某些保密数据,也是容易受到攻击的薄弱点。

因此,缓存是把双刃剑。

二、本地缓存 JDK Map

JDK Map 经常用于缓存实现:

HashMap

HashMap 是一种基于哈希表的集合类,它提供了快速的插入、查找和删除操作。可以将键值对作为缓存项的存储方式,将键作为缓存项的唯一标识符,值作为缓存项的内容。

ConcurrentHashMap

ConcurrentHashMap 是线程安全的 HashMap,它在多线程环境下可以保证高效的并发读写操作。

LinkedHashMap

LinkedHashMap 是一种有序的 HashMap ,它保留了元素插入的顺序,可以按照插入顺序或者访问顺序进行遍历。

TreeMap

TreeMap 是一种基于红黑树的有序 Map,它可以按照键的顺序进行遍历。

核心流程:

3、定时任务每隔 30 秒 ,执行缓存加载方法,刷新缓存。

笔者见过很多单体应用都使用这种方案,该方案的特点是简洁易用,工程实现也容易 。

三、本地缓存框架

虽然使用 JDK Map 能快捷构建缓存,但缓存的功能还是比较孱弱的。

因为现实场景里,我们可能需要给缓存添加缓存统计、过期失效、淘汰策略等功能。

于是,本地缓存框架应运而生。

流行的 Java 缓存框架包括: Ehcache , Google Guava , Caffine Cache 。

下图展示了 Caffine 框架的使用示例:

虽然本地缓存框架的功能很强大,但是本地缓存的缺陷依然明显。

高并发的场景,应用重启之后,本地缓存就失效了,系统的负载就比较大,需要花较长的时间才能恢复;

每个应用节点都会维护自己的单独缓存,缓存同步比较头疼。

四、分布式缓存

分布式缓存是指将缓存数据分布在多台机器上,以提高缓存容量和并发读写能力的缓存系统。分布式缓存通常由多台机器组成一个集群,每台机器上都运行着相同的缓存服务进程,缓存数据被均匀地分布在集群中的各个节点上。

Redis 是分布式缓存的首选,甚至我们一提到缓存,很多后端工程师首先想到的就它。

下图是神州专车订单的 Redis 集群架构 。将 Redis 集群拆分成四个分片,每个分片包含一主一从,主从可以切换。 应用 A 根据不同的缓存 key 访问不同的分片。

与本地缓存相比,分布式缓存具有以下优点:

容量和性能可扩展

通过增加集群中的机器数量,可以扩展缓存的容量和并发读写能力。同时,缓存数据对于应用来讲都是共享的。

高可用性

由于数据被分布在多台机器上,即使其中一台机器故障,缓存服务也能继续提供服务。

但是分布式缓存的缺点同样不容忽视:

复杂性

分布式缓存需要考虑序列化、数据分片、缓存大小等问题,相对于本地缓存而言更加复杂。

笔者曾经也认为无脑上缓存 ,系统就一定更快,但直到一次事故,对于分布式缓存的观念才彻底改变。

2014年,同事开发了比分直播的系统,所有的请求都是从分布式缓存 Memcached 中获取后直接响应。常规情况下,从缓存中查询数据非常快,但在线用户稍微多一点,整个系统就会特别卡。

通过 jstat 命令发现 GC 频率极高,几次请求就将新生代占满了,而且 CPU 的消耗都在 GC 线程上。初步判断是缓存值过大导致的,果不其然,缓存大小在 300k 到 500k 左右。

解决过程还比较波折,分为两个步骤:

修改新生代大小,从原来的 2G 修改成 4G,并精简缓存数据大小 (从平均 300k 左右降为 80k 左右);

把缓存拆成两个部分,第一部分是全量数据,第二部分是增量数据(数据量很小)。页面第一次请求拉取全量数据,当比分有变化的时候,通过 websocket 推送增量数据。

五、多级缓存

开源中国网站最开始完全是用本地缓存框架 Ehcache 。

后来随着访问量的激增,出现了一个可怕的问题:“因为 Java 程序更新很频繁,每次更新的时候都要重启。一旦重启后,整个 Ehcache 缓存里的数据都被清掉。重启后若大量访问进来的话,开源中国的数据库基本上很快就会崩掉”。

于是,开源中国开发了多级缓存框架 J2Cache,使用了多级缓存 Ehcache + Redis 。

多级缓存有如下优势:

离用户越近,速度越快;

减少分布式缓存查询频率,降低序列化和反序列化的 CPU 消耗;

本地缓存做为一级缓存,分布式缓存做为二级缓存,首先从一级缓存中查询,若能查询到数据则直接返回,否则从二级缓存中查询,若二级缓存中可以查询到数据,则回填到一级缓存中,并返回数据。若二级缓存也查询不到,则从数据源中查询,将结果分别回填到一级缓存,二级缓存中。

2018年,笔者服务的一家电商公司需要进行 app 首页接口的性能优化。笔者花了大概两天的时间完成了整个方案,采取的是两级缓存模式,同时利用了 Guava 的惰性加载机制,整体架构如下图所示:

缓存读取流程如下:

业务网关刚启动时,本地缓存没有数据,读取 Redis 缓存,如果 Redis 缓存也没数据,则通过 RPC 调用导购服务读取数据,然后再将数据写入本地缓存和 Redis 中;若 Redis 缓存不为空,则将缓存数据写入本地缓存中。

由于步骤1已经对本地缓存预热,后续请求直接读取本地缓存,返回给用户端。

Guava 配置了 refresh 机制,每隔一段时间会调用自定义 LoadingCache 线程池(5个最大线程,5个核心线程)去导购服务同步数据到本地缓存和 Redis 中。

优化后,性能表现很好,平均耗时在 5ms 左右。最开始我以为出现问题的几率很小,可是有一天晚上,突然发现 app 端首页显示的数据时而相同,时而不同。

也就是说: 虽然 LoadingCache 线程一直在调用接口更新缓存信息,但是各个 服务器本地缓存中的数据并非完成一致。 说明了两个很重要的点:

惰性加载仍然可能造成多台机器的数据不一致

LoadingCache 线程池数量配置的不太合理, 导致了线程堆积

最终,我们的解决方案是:

惰性加载结合消息机制来更新缓存数据,也就是:当导购服务的配置发生变化时,通知业务网关重新拉取数据,更新缓存。

适当调大 LoadigCache 的线程池参数,并在线程池埋点,监控线程池的使用情况,当线程繁忙时能发出告警,然后动态修改线程池参数。

六、没有银弹

没有银弹是 Fred Brooks 在 1987 年所发表的一篇关于软件工程的经典论文。

论文强调真正的银弹并不存在,而所谓的银弹则是指没有任何一项技术或方法可以能让软件工程的生产力在十年内提高十倍。

通俗来讲:在技术领域中没有一种通用的解决方案可以解决所有问题。

技术本质上是为了解决问题而存在的,每个问题都有其独特的环境和限制条件,没有一种通用的技术或工具可以完美地解决所有问题。

虽然技术不断发展和进步,但是对于复杂的问题,仍需要结合多种技术和方法,进行系统性的思考和综合性的解决方案设计,才能得到最优解决方案。

回到文章开头的问题 ,如何说服技术老大用 Redis ?

假如应用就是一个单体应用,缓存可以不共享,通过定时任务刷新缓存对业务没有影响,而且本地内存可以 Hold 住缓存的对象大小,那么你的技术老大的方案没有问题。

假如应用业务比较复杂,需要使用缓存提升系统的性能,同时分布式缓存共享的特性对于研发来讲开发更加快捷,Redis 确实是个不错的选择,可以从研发成本、代码维护、人力模型等多个角度和技术老大提出自己的观点。

总而言之,在技术领域中,没有银弹。我们需要不断探索和研究新的技术,但同时也需要认识到技术的局限性,不盲目追求所谓的“银弹”,而是结合具体问题和需求,选择最适合的解决方案。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
马伊琍:哺乳期搭档朱亚文拍吻戏,还有乳腺炎,是想让文章吃醋?

马伊琍:哺乳期搭档朱亚文拍吻戏,还有乳腺炎,是想让文章吃醋?

胥言
2024-05-31 17:58:11
泰国的电线杆真的很繁忙!

泰国的电线杆真的很繁忙!

悠闲葡萄
2024-06-01 12:54:04
城管队长出轨女下属称对方“嫩妈”,女主照片曝光真白瞎这张脸!

城管队长出轨女下属称对方“嫩妈”,女主照片曝光真白瞎这张脸!

听风听你
2024-05-30 20:29:17
活下去 像牲口一样的活下去

活下去 像牲口一样的活下去

四象八卦
2024-05-30 10:21:01
阿根廷的生活水平到底是什么样的?

阿根廷的生活水平到底是什么样的?

火山杂谈
2024-06-02 22:35:58
回顾88岁大爷侵犯48岁保姆,一天三次还不够,女保姆不堪受辱报警

回顾88岁大爷侵犯48岁保姆,一天三次还不够,女保姆不堪受辱报警

艾美讲故事
2024-06-02 07:32:36
蔡磊被质疑装病,网友指出疑点质问,感觉自己被戏耍,评论炸锅

蔡磊被质疑装病,网友指出疑点质问,感觉自己被戏耍,评论炸锅

娱乐的小灶
2024-06-03 10:54:15
这哪像47岁的人啊,简直就是30岁嘛!

这哪像47岁的人啊,简直就是30岁嘛!

小米虫侃人物
2024-06-03 09:07:40
香港人平均寿命为全球第一,港人的一些习惯,确实值得我们借鉴

香港人平均寿命为全球第一,港人的一些习惯,确实值得我们借鉴

影视解说阿相
2024-05-24 07:50:08
18国催着接收援助,为何越南要引起警惕?中方一项报告已揭露真相

18国催着接收援助,为何越南要引起警惕?中方一项报告已揭露真相

105度的世界
2024-06-03 11:00:17
19点30直播!中国女篮PK日本,韩旭李梦出征,姚明压阵,郑薇亮剑

19点30直播!中国女篮PK日本,韩旭李梦出征,姚明压阵,郑薇亮剑

小鬼头体育
2024-06-03 12:38:32
中菲两国海警船在仙宾礁海域追逐过程中险些发生碰撞!

中菲两国海警船在仙宾礁海域追逐过程中险些发生碰撞!

头条爆料007
2024-06-03 12:39:00
提前退休这支箭,射向了公务员队伍!

提前退休这支箭,射向了公务员队伍!

职场资深秘书
2024-05-24 06:49:05
92岁默多克第五次大婚,迎娶美女科学家,23岁混血女儿带男友出席

92岁默多克第五次大婚,迎娶美女科学家,23岁混血女儿带男友出席

译言
2024-06-02 18:41:53
为何香港六合彩在内地三十余年难以根治?

为何香港六合彩在内地三十余年难以根治?

雪莉故事汇
2024-06-03 07:49:10
德媒:德国工业正经历无声消亡

德媒:德国工业正经历无声消亡

参考消息
2024-06-02 21:44:05
中东局势一夜变天!莱希遇难后,沙特态度大变,中国走了步妙棋

中东局势一夜变天!莱希遇难后,沙特态度大变,中国走了步妙棋

星辰故事屋
2024-06-02 16:21:53
男子2000元搞定女邻居,发生20次关系后,女子终于忍无可忍:禽兽

男子2000元搞定女邻居,发生20次关系后,女子终于忍无可忍:禽兽

喵咪说事吖
2024-05-16 14:56:59
湖北省委组织部最新公示

湖北省委组织部最新公示

今日搞笑分享
2024-06-03 12:05:27
意甲大结局:亚特兰大精准控盘 做掉罗马踢欧冠 输佛罗伦萨收官

意甲大结局:亚特兰大精准控盘 做掉罗马踢欧冠 输佛罗伦萨收官

智道足球
2024-06-03 08:28:37
2024-06-03 15:40:49
汪亚萍爱音乐
汪亚萍爱音乐
这个风景不错加油宝贝
946文章数 187关注度
往期回顾 全部

科技要闻

2万字演讲|黄仁勋剧透 未来3年新品有这些

头条要闻

白宫:拜登明白允许乌军使用美国武器打击俄领土的后果

头条要闻

白宫:拜登明白允许乌军使用美国武器打击俄领土的后果

体育要闻

万人空巷!皇马举行欧冠夺冠庆典

娱乐要闻

混战升级!编剧赵冬苓力挺王阳遭围攻

财经要闻

接班100天,宗馥莉急了

汽车要闻

搭载华为HiCAR 传祺M6 MAX售14.58万元

态度原创

教育
时尚
数码
艺术
军事航空

教育要闻

我家小孩7岁能开汽车!家长发圈炫耀,该给玩心大的家长立法了!

为什么我劝中年男人:衣不穿紧、不塞衣角?看这3组对比就明白了

数码要闻

超高性价比显卡选择,蓝戟 intel显卡618选购参考

艺术要闻

穿越时空的艺术:《马可·波罗》AI沉浸影片探索人类文明

军事要闻

朝国防省:朝方将暂停向韩方投放垃圾

无障碍浏览 进入关怀版