哈喽,大家好, 最近想动手写一个localcache练练手,工作这么久了,也看过很多同事实现的本地缓存,都各有所长,自己平时也在思考如何实现一个高性能的本地缓存,接下来我将基于自己的理解实现一版本地缓存,欢迎各位大佬们提出宝贵意见,我会根据意见不断完善的。
本篇主要介绍设计一个本地缓存都要考虑什么点,后续为实现文章,欢迎关注这个系列。
随着互联网的普及,用户数和访问量越来越大,这就需要我们的应用支撑更多的并发量,比如某宝的首页流量,大量的用户同时进入首页,对我们的应用服务器和数据库服务器造成的计算也是巨大的,本身数据库访问就占用数据库连接,导致网络开销巨大,在面对如此高的并发量下,数据库就会面临瓶颈,这时就要考虑加缓存,缓存就分为分布式缓存和本地缓存,大多数场景我们使用分布式缓存就可以满足要求,分布式缓存访问速度也很快,但是数据需要跨网络传输,在面对首页这种高并发量级下,对性能要求是很高的,不能放过一点点的性能优化空间,这时我们就可以选择使用本地缓存来提高性能,本地缓存不需要跨网络传输,应用和cache都在同一个进程内部,快速请求,适用于首页这种数据更新频率较低的业务场景。
综上所述,我们往往使用本地缓存后的系统架构是这样的:
本地缓存虽然带来性能优化,不过也是有一些弊端的,缓存与应用程序耦合,多个应用程序无法直接的共享缓存,各应用或集群的各节点都需要维护自己的单独缓存,对内存是一种浪费,使用缓存的是我们程序员自己,我们要根据根据数据类型、业务场景来准确判断使用何种类型的缓存,如何使用这种缓存,以最小的成本最快的效率达到最优的目的。
第一步我们就要考虑数据该怎样存储;数据的查找效率要高,首先我们就想到了哈希表,哈希表的查找效率高,时间复杂度为O(1)
,可以满足我们的需求;确定是使用什么结构来存储,接下来我们要考虑以什么类型进行存储,因为不同的业务场景使用的数据类型不同,为了通用,在java
中我们可以使用泛型,Go
语言中暂时没有泛型,我们可以使用interface
类型来代替,把解析数据交给程序员自己来进行断言,增强了可扩展性,同时也增加一些风险。
总结:
key
:string
类型;value
:interface
类型;本地缓存的应用肯定会面对并发读写的场景,这是就要考虑并发安全的问题。因为我们选择的是哈希结构,Go
语言中主要提供了两种哈希,一种是非线程安全的map
,一种是线程安全的sync.map
,为了方便我们可以直接选择sync.map
,也可以考虑使用map
+sync.RWMutex
组合方式自己实现保证线程安全,网上有人对这两种方式进行比较,在读操作远多于写操作的时候,使用sync.map
的性能是远高于map
+sync.RWMutex
的组合的。在本地缓存中读操作是远高于写操作的,但是我们本地缓存不仅支持进行数据存储的时候要使用锁,进行过期清除等操作时也需要加锁,所以使用map+sync.RWMutex
的方式更灵活,所以这里我们选择这种方式保证并发安全。
加锁可以保证数据的读写安全性,但是会增加锁竞争,本地缓存本来就是为了提升性能而设计出来,不能让其成为性能瓶颈,所以我们要对锁竞争进行优化。针对本地缓存的应用场景,我们可以根据key
进行分桶处理,减少锁竞争。
我们的key
都是string
类型,所以我们可以使用djb2
哈希算法把key
打散进行分桶,然后在对每一个桶进行加锁,也就是锁细化,减少竞争。
因为本地缓存是在内存中存储的,内存都是有限制的,我们不可能无限存储,所以我们可以指定缓存对象的数量,根据我们具体的应用场景去预估这个上限值,默认我们选择缓存的数量为1024。
因为我们会设置缓存对象的数量,当触发上限值时,可以使用淘汰策略淘汰掉,常见的缓存淘汰算法有:
LFU
(Least Frequently Used)即最近不常用算法,根据数据的历史访问频率来淘汰数据,这种算法核心思想认为最近使用频率低的数据,很大概率不会再使用,把使用频率最小的数据置换出去。
存在的问题:
某些数据在短时间内被高频访问,在之后的很长一段时间不再被访问,因为之前的访问频率急剧增加,那么在之后不会在短时间内被淘汰,占据着队列前头的位置,会导致更频繁使用的块更容易被清除掉,刚进入的缓存新数据也可能会很快的被删除。
LRU
(Least Recently User)即最近最少使用算法,根据数据的历史访问记录来淘汰数据,这种算法核心思想认为最近使用的数据很大概率会再次使用,最近一段时间没有使用的数据,很大概率不会再次使用,把最长时间未被访问的数据置换出去
存在问题:
当某个客户端访问了大量的历史数据时,可能会使缓存中的数据被历史数据替换,降低缓存命中率。
FIFO
(First in First out)即先进先出算法,这种算法的核心思想是最近刚访问的,将来访问的可能性比较大,先进入缓存的数据最先被淘汰掉。
存在的问题:
这种算法采用绝对公平的方式进行数据置换,很容易发生缺页中断问题。
Two Queues
是FIFO
+ LRU
的结合,其核心思想是当数据第一次访问时,将数据缓存在FIFO
队列中,当数据第二次被访问时将数据从FIFO
队列移到LRU
队列里面,这两个队列按照自己的方法淘汰数据。
存在问题:
这种算法和LRU-2
一致,适应性差,存在LRU
中的数据需要大量的访问才会将历史记录清除掉。
ARU
(Adaptive Replacement Cache)即自适应缓存替换算法,是LFU
和LRU
算法的结合使用,其核心思想是根据被淘汰数据的访问情况,而增加对应 LRU
还是 LFU
链表的大小,ARU
主要包含了四个链表,LRU
和 LRU Ghost
,LFU
和LFU Ghost
, Ghost
链表为对应淘汰的数据记录链表,不记录数据,只记录 ID 等信息。
截屏2021-12-04 下午6.52.05
当数据被访问时加入LRU
队列,如果该数据再次被访问,则同时被放到 LFU
链表中;如果该数据在LRU
队列中淘汰了,那么该数据进入LRU Ghost
队列,如果之后该数据在之后被再次访问了,就增加LRU
队列的大小,同时缩减LFU
队列的大小。
存在问题:
因为要维护四个队列,会占用更多的内存空间。
每一种算法都有自己特色,结合我们本地缓存使用的场景,选择ARU
算法来做缓存缓存淘汰策略是一个不错的选择,可以动态调整 LRU 和 LFU 的大小,以适应当前最佳的缓存命中。
除了使用缓存淘汰策略清除数据外,还可以添加一个过期时间做双重保证,避免不经常访问的数据一直占用内存。可以有两种做法:
两种做法各有利弊,异步更新数据需要具体业务场景选择,为了迎合大多数业务,我们采用数据过期了直接删除这种方法更友好,这里我们采用懒加载的方式,在获取数据的时候判断数据是否过期,同时设置一个定时任务,每天定时删除过期的数据。
很多人对于缓存的监控也比较忽略,基本写完后不报错就默认他已经生效了,这就无法感知这个缓存是否起作用了,所以对于缓存各种指标的监控,也比较重要,通过其不同的指标数据,我们可以对缓存的参数进行优化,从而让缓存达到最优化。如果是企业应用,我们可以使用Prometheus
进行监控上报,我们自测可以简单写一个小组件,定时打印缓存数、缓存命中率等指标。
对于大量使用本地缓存的应用,由于涉及到缓存淘汰,那么GC问题必定是常事。如果出现GC较多,STW时间较长,那么必定会影响服务可用性;对于这个事项一般是具体case具体分析,本地缓存上线后记得经常查看GC
监控。
使用缓存就要考虑缓存穿透的问题,不过这个一般不在本地缓存中实现,基本交给使用者来实现,当在缓存中找不到元素时,它设置对缓存键的锁定;这样其他线程将等待此元素被填充,而不是命中数据库(外部使用singleflight
封装一下)。
真正想设计一个高性能的本地缓存还是挺不容易的,由于我也才疏学浅,本文的设计思想也是个人实践想法,欢迎大家提出宝贵意见,我们一起做出来一个真正的高性能本地缓存。
下篇文章我将分享自己的写的一个本地缓存,尽请期待!!!
本文由哈喽比特于2年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/ZtSA3J8HK4QarhrJwBQtXw
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。