专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

聊一聊高并发系统基石之一的缓存,会用很简单,用好才是技术活

  大家好,又见面了。
  在服务端开发中,缓存常常被当做系统性能扛压的不二之选。在实施方案上,缓存使用策略虽有一定普适性,却也并非完全绝对,需要结合实际的项目诉求与场景进行综合权衡与考量,进而得出符合自己项目的最佳实践。缓存使用的演进
  现有这么一个系统:
  一个互动论坛系统,用户登录系统之后,可以在论坛上查看帖子列表、查看帖子详情、发表帖子、评论帖子、为帖子点赞等操作。
  系统中所有的配置数据与业务数据均存储在数据库中。随着业务的发展,注册用户量越来越多,然后整个系统的响应速度也越来越慢,用户体验越来越差,用户逐渐出现流失。本地缓存的牛刀小试
  为了挽救这一局面,开发人员需要介入去分析性能瓶颈并尝试优化提升响应速度,并很快找到响应慢的瓶颈在数据库的频繁操作,于是想到了使用缓存来解决问题。
  于是,开发人员在项目中使用了基于接口维度的短期缓存,对每个接口的请求参数(帖子ID)与响应内容缓存一定的时间(比如1分钟),对于相同的请求,如果匹配到缓存则直接返回缓存的结果即可,不用再次去执行查询数据库以及业务维度的运算逻辑。
  JAVA中有很多的开源框架都有提供类似的能力支持,比如Ehcache或者GuavaCache、CaffeineCache等,可以通过简单的添加注解的方式就实现上述需要的缓存效果。比如使用Ehcache来实现接口接口缓存的时候,代码使用方式如下(这里先简单的演示下,后续的系列文档中会专门对这些框架进行深入的探讨):Cacheable(valueUserDetailCache,keyuserId)publicUserDetailqueryUserDetailById(StringuserId){UserEntityuserEntityuserMapper。queryByUserId(userId);returnconvertEntityToUserDetail(userEntity);}复制代码
  基上面的本地缓存策略改动后重新上线,整体的响应性能上果然提升了很多。本地缓存的策略虽然有效地提升了处理请求的速度,但新的问题也随之浮现。有用户反馈,社区内的帖子列表多次刷新后会出现内容不一致的情况,有的帖子刷新之后会从列表消失,多次刷新后偶尔会出现。
  其实这就是本地缓存在集群多节点场景下会遇到的一个很常见的缓存漂移现象:
  因为业务集群存在多个节点,而缓存是每个业务节点本地独立构建的,所以才出现了更新场景导致的本地缓存不一致的问题,进而表现为上述问题现象。集中式缓存的初露锋芒
  为了解决集群内多个节点间执行写操作之后,各节点本地缓存不一致的问题,开发人员想到可以构建一个集中式缓存,然后所有业务节点都读取或者更新同一份缓存数据,这样就可以完美地解决节点间缓存不一致的问题了。
  业界成熟的集中式缓存有很多,最出名的莫过于很多人都耳熟能详的Redis,或者是在各种面试中常常被拿来与Redis进行比较的Memcached。也正是由于它们出色的自身性能表现,在当前的各种分布式系统中,Redis近乎已经成为了一种标配,常常与MySQL等持久化数据库搭配使用,放在数据库前面进行扛压。比如下面图中示例的一种最简化版本的组网架构:
  开发人员对缓存进行了整改,将本地缓存改为了Redis集中式缓存。这样一来:缓存不一致问题解决:解决了各个节点间数据不一致的问题。单机内存容量限制解决:使用了Redis这种分布式的集中式缓存,扩大了内存缓存的容量范围,可以顺便将很多业务层面的数据全部加载到Redis中分片进行缓存,性能也相比而言得到了提升。
  似乎使用集中式缓存已经是分布式系统中的最优解了,但是现实情况真的就这么简单么?也不尽然!多级缓存的珠联璧合
  在尝到了集中式缓存的甜头之后,暖心的程序员们想到要彻底为数据库减压,将所有业务中需要频繁使用的数据全部同步存储到Redis中,然后业务使用的时候直接从Redis中获取相关数据,大大地减少了数据库的请求频次。但是改完上线之后,发现有些处理流程中并没有太大的性能提升。缘何如此?只因为对集中式缓存的过分滥用!分析发现这些流程的处理需要涉及大量的交互与数据整合逻辑,一个流程需要访问近乎30次Redis!虽然Redis的单次请求处理性能极高,甚至可以达到微秒级别的响应速度,但是每个流程里面几十次的网络IO交互,导致频繁的IO请求,以及线程的阻塞与唤醒切换交替,使得系统在线程上下文切换层面浪费巨大。
  那么,要想破局,最常规的手段便是尝试降低对集中式缓存(如Redis)的请求数量,降低网络IO交互次数。而如何来降低呢?又回到了本地缓存!集中式缓存并非是分布式系统中提升性能的银弹,但我们可以将本地缓存与集中式缓存结合起来使用,取长补短,实现效果最大化。如图所示:
  上图演示的也即多级缓存的策略。具体而言:对于一些变更频率比较高的数据,采用集中式缓存,这样可以确保数据变更之后所有节点都可以实时感知到,确保数据一致;对于一些极少变更的数据(比如一些系统配置项)或者是一些对短期一致性要求不高的数据(比如用户昵称、签名等)则采用本地缓存,大大减少对远端集中式缓存的网络IO次数。
  这样一来,系统的响应性能又得到了进一步的提升。
  通过对缓存使用策略的一步步演进,我们可以感受到缓存的恰当使用对系统性能的帮助作用。
  无处不在的缓存
  缓存存在的初衷,就是为了兼容两个处理速度不一致的场景对接适配的。在我们的日常生活中,也常常可以看到缓存的影子。比如对于几年前比较盛行的那种带桶的净水器(见下图),由于净水的功率比较小,导致实时过滤得到纯净水的水流特别的缓慢,用户倒一杯水要等2分钟,体验太差,所以配了个蓄水桶,净水机先慢慢的将净化后的水存储到桶中,然后用户倒水的时候可以从桶里快速的倒出,无需焦急等待这个蓄水桶,便是一个缓存器。
  编码源于生活,CPU的高速缓存设计就是这一生活实践在计算机领域的原样复制。缓存可以说在软件世界里无处不在,除了我们自己的业务系统外,在网络传输、操作系统、中间件、基础框架中都可以看到缓存的影子。如:网络传输场景。
  比如ARP协议,基于ARP缓存表进行IP与终端硬件MAC地址之间的缓存映射。这样与对端主机之间有通信需求的时候,就可以在ARP缓存中查找到IP对应的对端设备MAC地址,避免每次请求都需要去发送ARP请求查询MAC地址。MyBatis的多级缓存。
  MyBatis作为JAVA体系中被广泛使用的数据库操作框架,其内部为了提升处理效率,构建了一级缓存与二级缓存,大大减少了对SQL的重复执行次数。CPU中的缓存。
  CPU与内存之间有个临时存储器(高速缓存),容量虽比内存小,但是处理速度却远快于普通内存。高速缓存的机制,有效地解决了CPU运算速度与内存读写速度不匹配的问题。
  缓存的使用场景
  缓存作为互联网类软件系统架构与实现中的基石般的存在,不仅仅是在系统扛压或者接口处理速度提升等性能优化方案,在其他多个方面都可以发挥其独一无二的关键价值。下面就让我们一起来看看缓存都可以用在哪些场景上,可以解决我们哪方面的痛点。降低自身CPU消耗
  如前面章节中提到的项目实例,缓存最典型的使用场景就是用在系统的性能优化上。而在性能优化层面,一个经典的策略就是空间换时间。比如:在数据库表中做一些字段冗备。
  比如用户表TUser和部门表TDepartment,在TUser表中除了有个DepartmentId字段与TDepartment表进行关联之外,还额外在TUser表中存储DepartmentName值。这样在很多需要展示用户所属部门信息的时候就省去了多表关联查询的操作。
  对一些中间处理结果进行存储。
  比如系统中的数据报表模块,需要对整个系统内所有的关联业务数据进行计算统计,且需要多张表多来源数据之间的综合汇总之后才能得到最终的结果,整个过程的计算非常的耗时。如果借助缓存,则可以将一些中间计算结果进行暂存,然后报表请求中基于中间结果进行二次简单处理即可。这样可以大大降低基于请求触发的实时计算量。
  在空间换时间实施策略中,缓存是该策略的核心、也是被使用的最为广泛的一种方案。借助缓存,可以将一些CPU耗时计算的处理结果进行缓存复用,以降低重复计算工作量,达到降低CPU占用的效果。
  减少对外IO交互
  上面介绍的使用缓存是为了不断降低请求处理时对自身CPU占用,进而提升服务的处理性能。这里我们介绍缓存的另一典型使用场景,就是减少系统对外依赖的请求频次。即通过将一些从远端请求回来的响应结果进行缓存,后面直接使用此缓存结果而无需再次发起网络IO请求交互。
  对于服务端而言,通过构建缓存的方式来减少自身对外的IO请求,主要有几个考量出发点:从自身性能层面考虑,减少对外IO操作,降低了对外接口的响应时延,也对服务端自身处理性能有一定提升。从对端服务稳定性层面考虑,避免对端服务负载过大。很多时候调用方和被调用方系统的承压能力是不匹配的,甚至有些被调用方系统可能是不承压的。为了避免将对端服务压垮,需要调用方缓存请求结果,降低IO请求。从自身可靠性层面而言,将一些远端服务请求到的结果缓存起来,即使远端服务出现故障,自身业务依旧可以基于缓存数据进行正常业务处理,起到一个兜底作用,提升自身的抗风险能力。
  在分布式系统服务治理范畴内,服务注册管理服务是必不可少的,比如SpringCloud家族的Eureka,或者是Alibaba开源的Nacos。它们对于缓存的利用,可以说是对上面所提几点的完美阐述。
  以Nacos为例:
  除了上述的因素之外,对一些移动端APP或者H5界面而言,缓存的使用还有一个层面的考虑,即降低用户的流量消耗,通过将一些资源类数据缓存到本地,避免反复去下载,给用户省点流量,也可以提升用户的使用体验(界面渲染速度快,减少出现白屏等待的情况)。
  提升用户个性化体验
  缓存除了在系统性能提升或系统可靠性兜底等场景发挥价值外,在APP或者web类用户侧产品中,还经常被用于存储一些临时非永久的个性化使用习惯配置或者身份数据,以提升用户的个性化使用体验。缓存cookie、session等身份鉴权信息,这样就可以避免用户每次访问都需要进行身份验证。
  记住一些用户上次操作习惯,比如用户在一个页面上将列表分页查询设置为100条页,则后续在系统内访问其它列表页面时,都沿用这一设置。缓存用户的一些本地设置,这个主要是APP端常用的功能,可以在缓存中保存些与当前设备绑定的设置信息,仅对当前设备有效。比如同一个账号登录某个APP,用户希望在手机端可以显示深色主题,而PAD端则显示浅色主体,这种基于设备的个性化设置,可以缓存到设备本身即可。
  业务与缓存的集成模式
  如前所述,我们可以在不同的方面使用缓存来辅助达成项目在某些方面的诉求。而根据使用场景的不同,在结合缓存进行业务逻辑实现的时候,也会存在不同的架构模式,典型的会有旁路型缓存、穿透型缓存与异步型缓存三种。旁路型缓存
  在旁路型缓存模式中,业务自行负责与缓存以及数据库之间的交互,可以自由决定缓存未命中场景的处理策略,更加契合大部分业务场景的定制化诉求。
  由于业务模块自行实现缓存与数据库之间的数据写入与更新的逻辑,实际实现的时候需要注意下在高并发场景的数据一致性问题,以及可能会出现的缓存击穿、缓存穿透、缓存雪崩等问题的防护。
  旁路型缓存是实际业务中最常使用的一种架构模式,在后面的内容中,我们还会不断的涉及到旁路缓存中相关的内容。
  穿透型缓存
  穿透型缓存在实际业务中使用的较少,主要是应用在一些缓存类的中间件中,或者在一些大型系统中专门的数据管理模块中使用。
  一般情况下,业务使用缓存的时候,会是先尝试读取缓存,在尝试读取DB,而使用穿透型缓存架构时,会有专门模块将这些动作封装成黑盒的,业务模块不会与数据库进行直接交互。如下图所示:
  这种模式对业务而言是比较友好的,业务只需调用缓存接口即可,无需自行实现缓存与DB之间的交互策略。异步型缓存
  还有一种缓存的使用模式,可以看作是穿透型缓存的演进异化版本,其使用场景也相对较少,即异步型缓存。其主要策略就是业务侧请求的实时读写交互都是基于缓存进行,任何数据的读写也完全基于缓存进行操作。此外,单独实现一个数据持久化操作(独立线程或者进程中执行),用于将缓存中变更的数据写入到数据库中。
  这种情况,实时业务读写请求完全基于缓存进行,而将数据库仅仅作为一个数据持久化存储的备份盘。由于实时业务请求仅与缓存进行交互,所以在性能上可以得到更好的表现。但是这种模式也存在一个致命的问题:数据可靠性!因为是异步操作,所以在下一次数据写入DB前,会有一段时间数据仅存在于缓存中,一旦缓存服务宕机,这部分数据将会丢失。所以这种模式仅适用于对数据一致性要求不是特别高的场景。缓存的优秀实践
  缓存与持久化存储的一个很大的不同点就是缓存的定位应该是一种辅助角色,是一种锦上添花般的存在。
  缓存也是一把双刃剑,基于缓存可以大幅提升我们的系统并发与承压能力,但稍不留神也可能会让我们的系统陷入灭顶之灾。所以我们在决定使用缓存的时候,需要知晓缓存设计与使用的一些关键要点,才可以让我们在使用的时候更加游刃有余。可删除重建
  可删除重建,这是缓存与持久化存储最大的一个差别。缓存的定位一定是为了辅助业务处理而生的,也就是说缓存有则使用,没有也不会影响到我们具体的业务运转。此外,即使我们的缓存数据除了问题,我们也可以将其删除重建。
  这一点在APP类的产品中体现的会比较明显。比如对于微信APP的缓存,就有明确的提示说缓存可以删除而不会影响其功能使用:
  同样地,我们也可以去放心的清理浏览器的缓存,而不用担心清理之后我们浏览器或者网页的功能会出现异常(最多就是需要重新下载或者重建缓存数据,速度会有一些慢)。
  相同的逻辑,在服务端构建的一些缓存,也应该具备此特性。比如基于内存的缓存,当业务进程重启后,应该有途径可以将缓存重建出来(比如从MySQL中加载数据然后构建缓存,或者是缓存从0开始基于请求触发而构建)。
  有兜底屏障
  缓存作为高并发类系统中的核心组件,负责抗住大部分的并发请求,一旦缓存组件出问题,往往对整个系统会造成毁灭性的打击。所以我们的缓存在实现的时候必须要有充足且完备的兜底与自恢复机制。需要做到以下几点:关注下缓存数据量超出承受范围的处理策略,比如定好数据的淘汰机制。避免缓存集中失效,比如批量加载数据到缓存的时候随机打散过期时间,避免同一时间大批量缓存失效引发缓存雪崩问题。有效地冷数据预热加载机制,以及热点数据防过期机制,避免出现大量对冷数据的请求无法命中缓存或者热点数据突然失效,导致缓存击穿问题。合理的防身自保手段,比如采用布隆过滤器机制,避免被恶意请求攻陷,导致缓存穿透类的问题。
  缓存的可靠性与兜底策略设计,是一个宏大且宽泛的命题,在本系列专栏后续的文章中,我们会逐个深入的探讨。
  关注缓存的一致性保证
  在高并发类的系统中进行数据更新的时候,缓存与数据库的数据一致性问题,是一个永远无法绕过的话题。对于基于旁路型缓存的大部分业务而言,数据更新操作,一般可以组合出几种不同的处理策略:先更新缓存,再更新数据库先更新数据库,再更新缓存先删除缓存,再更新数据库先更新数据库,再删除缓存
  由于大部分数据库都支持事务,而几乎所有的缓存操作都不具有事务性。所以在一些写操作并发不是特别高且一致性要求不是特别强烈的情况下,可以简单的借助数据库的事务进行控制。比如先更新数据库再更新缓存,如果缓存更新失败则回滚数据库事务。
  然而在一些并发请求特别高的时候,基于事务控制来保证数据一致性往往会对性能造成影响,且事务隔离级别设置的越高影响越大,所以也可以采用一些其它辅助策略,来替代事务的控制,如重试机制、或异步补偿机制、或多者结合方式等。
  比如下图所示的这种策略:
  上图的数据更新处理策略,可以有效地保证数据的最终一致性,降低极端情况可能出现数据不一致的概率,并兜底增加了数据不一致时的自恢复能力。
  数据一致性保证作为缓存的另一个重要命题,我们会在本系列专栏后续的文章中专门进行深入的剖析。
  总结回顾
  本篇文章的内容中,我们对缓存的各个方面进行了一个简单的阐述与了解,也可以看出缓存对于一个软件系统的重要价值。通过对缓存的合理、充分利用,可以大大的增强我们的系统承压性能、提升产品的用户体验。
  缓存作为高并发系统中的神兵利器被广泛使用,堪称高并发系统的基石之一。而缓存的内容还远远不止我们本篇文档中所介绍的这些、它是一个非常宏大的命题。
  为了能够将缓存的方方面面彻底的讲透、讲全,在接下来的一段时间里,我会以系列专栏的形式,从不同的角度对缓存的方方面面进行探讨。不仅仅着眼于如何去使用缓存、也一起聊聊缓存设计中的一些哲学理念这一点是我觉得更有价值的一点,因为这些理念对提升我们的软件架构认知、完善我们的软件设计思维有很大的指导与借鉴意义。
  作者:架构悟道
  链接:https:juejin。cnpost7151937376578142216
  来源:稀土掘金
  著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

杨席兵美国拼命加息是通胀降温,还是给美元打气?杨席兵美国拼命加息是通胀降温,还是给美元打气?2022年,美国拼命加息,从年初的00。25,己加到33。253次加息0。75。美联储官员扬言,到12月利率将达到4,并在2023年之美国载人登月疑云重重!也许永远成谜美国登月火箭再次推迟发射,此前是因为雷劈和液氢泄露的原因。美国为什么要抢在中国登月之前抢先登月?关于美国登月最近再次被引起热议的是我国驻日大使薛剑的一篇转发。由此我们看出作为一个举男人的几种克制,只留给真爱的女人喜欢会放肆,而爱则是克制。真正爱着的人,极少被放肆与纵容以待,而是各种态度与表现都有些体面与完满。虽说爱一个人就是一场甘愿的付出与奔赴,可是事情降临到自己身上时,难免有些私人欲望与他是布衣元帅之子,25岁入清华,58岁授中将,岳父是开国少将这位将军是红色子弟,父亲是鼎鼎大名的布衣元帅徐向前,但他并未因此生出骄纵之情,一直低调生活,恪守本心,努力学习提升自己。后来继承父辈的志向,加入到解放军中,一步一个脚印升迁为将军,关于哈尔滨宗教文化的记忆在宗教领域方面哈尔滨也和全国一样,从解放后到现在经历了三起三落,不夸张的说是在夹缝中艰难的生存,目前的正常化是从八十年代初中共中央发布的关于宗教信仰自由的19号文件才开始稳定发展的十一正式开放!蚌埠市南山公园新颜一睹为快小南山及周边地区自民国以来就一直是蚌埠市民主要的休闲活动场所,见证了城市的发展成长,但随着城市化现代化的快速发展,小南山作为蚌埠的母亲山以及蚌埠最早的市民公园,其公园空间存在感服务广州旅游十大景点推荐广州是著名的旅游城市,那么广州著名景点有哪些呢?广州最著名景点包括广州长隆白云山广州塔越秀公园陈家祠华南植物园宝墨园等,今天小伟8分享来广州一定要去的十大景点,收藏不迷路。广州白云50张来自西班牙的有趣照片西班牙是欧洲第四大国,也是一个体育强国。它拥有复杂的城市和平坦的平原,以及白雪皑皑的山脉,所有这些都使它成为一个受欢迎的旅游目的地。西班牙隆达的新桥是地球上最美丽的地方之一巴塞罗那1979年对越反击战,张万年的发明让越南人有来无回,立下赫赫战功张万年曾经在对越反击战中面对敌人女特工的偷袭,张万年发明并使用一条战法就让这些女特工无处遁形,那么张万年将军用的是什么方法呢?1968年已经是原广州军区作战部副部长的张万年,突然接源远流长的中华元素千百年来,中华民族以龙的传人而深感自豪,中华大地被称作龙的土地,龙已成为中华民族的崇高徽号。索本求源,龙图腾就起源于位居我国上古三皇之首的伏羲,伏羲也称太昊。是我国远古神话传说中的毛岸英牺牲后,刘思齐改嫁杨茂之生四个孩子,杨茂之是做什么的?1950年的冬天,从朝鲜传回来一个噩耗,毛主席的长子毛岸英不幸在美军的一次轰炸中壮烈牺牲。消息传回国内,得到消息的人都被震惊了,此时距离毛岸英远赴朝鲜参战才一个月的时间。作为毛主席
中方积极表态后,菲律宾考虑求助日本修铁路,此前曾拒绝该国贷款据环球网18日报道,菲律宾铁路修建项目此前引发了大量关注,经过一段时间的停滞以后,眼下这一项目又迎来了新进展。日本外交大臣林芳正在前一天与菲律宾总统进行了电话会议,双方就地区局势和2008年,钱学森侄子获得诺贝尔奖,却当众扬言我不是中国人我是一名美国的科学家,这是毋庸置疑的。我并非中国人。我的血脉不能证明我来自哪里。身怀中国血统的科学家,拥有中国特别行政区颁发的中国文凭,却对中国充满了怨言。钱永健的所作所为,让所有彻底摆烂?约翰逊刚因缺席政府活动被批,本月二次度假再遭抨击文吴军捷工作室李不言卸任在即,英国首相约翰逊似乎要彻底摆烂一般,此前刚因频繁缺席政府重要活动和会议而受到批评,如今又将和新婚妻子前往希腊休假一周,引发了英国民众的怒火。民众认为他首普京霸气出招,俄军驱逐英国军机,约翰逊却失声了狭路相逢勇者胜,这句话真没说错。俄罗斯国防部在日前表示,一架英国侦察机曾试图在15日闯入俄罗斯领空,但随后被俄军战机驱逐了。至于俄军米格31战机是如何驱逐英国军机的期间有没有开火,本土确诊突破500万例,蔡当局却准备重新开放台湾?前一段时间,台海地区风起云涌,美国众议院议长佩洛西窜访台湾,造成两岸局势紧张,甚至有外界评论指,两岸关系最糟糕或可能出现擦枪走火的情况。蔡英文不嫌事大,随后又接待了其它的美国会议员中国会偷袭关岛,让它变成美国第二个珍珠港?美国为何制造此舆论中国可能要偷袭关岛,关岛会成为美国的第二个珍珠港。如果各位网友看到这样的标题或听到这样的新闻会做何反应?可能吗?中国为什么要偷袭呢?是中国对美国的反击吧!肯定是美国对中国开战了,中草帽姐要发100万助学金从星光大道走红的草帽姐,为广大观众所认识。近期,给村里考上大学的几名学子发了助学金,并且发出豪言壮志谁考上清华或者北大,奖励100万,我滴个天,不少钱了!草帽姐成名以后,就有点飘了55年授衔前彭总大骂一位上将,叶帅劝了句什么话,彭总低头不语?1955年全军授衔前,军队正在制定完善管理条例。时任副总长训练总监部副部长的彭绍辉,亲自到国防部向彭老总解释说明相关材料。在一处细节问题上,彭老总提出了自己的意见,让彭绍辉进行修改任总的话,听还是不听?任正非一个内部讲话,不仅全网刷屏,而且还引发周三的股市崩盘,各大自媒体更是各抒己见,有人赞同,有人反对,到底该听哪一方,难以决策。正方说未来五到十年,不仅是我们经济的至暗时刻,也是图解三孚股份中报第二季度单季净利润同比增168。30三孚股份2022中报显示,公司主营收入13。4亿元,同比上升111。05归母净利润4。05亿元,同比上升173。84扣非净利润4。01亿元,同比上升176。32其中2022年第二季让青年科研人员轻装上阵向秋减负就是要把不合理的负担减掉为充分激发青年科研人员创新活力,近期,科技部财政部教育部中科院自然科学基金委五部门联合印发关于开展减轻青年科研人员负担专项行动的通知,围绕青年科研人
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网