缓存技术使用的实践思考分析

按照现在流行的互联网分层架构模型,最简单的架构当属Web响应层+DB存储层的架构。从最开始的单机混合部署Web和DB,到后来将二者拆分到不同物理机以避免共享机器硬件带来的性能瓶颈,再随着流量的增长,Web应用变为集群部署模式,而DB则衍生出主从机来保证高可用,同时便于实现读写分离。这一连串系统架构的升级,本质上是为了追求更高的性能,达到更低的延时。

缘起:为何使用缓存

在应用对外提供服务时,其稳定性受到诸多因素影响,其中比较重要的有CPU、内存、IO(磁盘IO、网络IO)等,这些硬件资源十分宝贵,因此对于那些需要经过复杂计算才能得到结果的,或者需要频繁读取磁盘数据的,最好将结果缓存起来,避免资源的重复消耗。

CPU瓶颈

如果项目中有很多正则表达式计算,或者某个计算结果是多次中间结果合并后才得出的,且CPU的使用率一直居高不下,那么就可以考虑是否应该将这些结果缓存起来,根据特定Key直接获取Value结果,减少中间链路的传递过程,减少CPU的使用率。

IO瓶颈

众所周知,从磁盘获取数据受到磁盘转速、寻道速度、磁盘缓冲区大小等诸多因素影响,这些因素决定了磁盘的IOPS,同时我们也知道对于数据的读写来说,CPU的缓存读写速度> 内存的读写速度>磁盘的读写速度。虽然磁盘内部也配备了缓存以匹配内存的读写速度,但其容量毕竟是有限的,那么当磁盘的IOPS无法进一步提升的时候,便会想到将数据缓存到内存中,从而降低磁盘的访问压力。这一策略常被应用于缓解DB数据库的数据访问压力。

选择本地缓存和分布式缓存的考量点

既然可以使用缓存来提升系统吞吐能力,那么紧接着遇到的问题就是选择本地缓存,还是分布式缓存?什么时候需要使用多级缓存呢?接下来,让我们聊一聊在使用缓存优化项目的过程中,本地缓存和分布式缓存的应用场景和优缺点。

本地缓存的优缺点和应用场景

统一进程带来了以下优势:

  • 由于本地缓存和应用在同一个进程中,因而其稳定性很高,达到了和应用同生共死的境界;
  • 由于在同一进程中,避免了网络数据传输带来的消耗,所有缓存数据直接从进程所在的内存区域获取即可。

强耦合性也会导致以下这些劣势:

  • 本地缓存和应用共享一片内存,争抢内存资源,无法水平扩展,且可能造成频繁的GC,影响线上应用的稳定性。
  • 由于没有持久化机制,在项目重启后缓存内数据就会丢失,对于高频访问数据,需要对数据进行预热操作。
  • 多份进程内缓存存储着同样的数据内容,造成内存使用浪费。
  • 同样的数据存储在不同的本地机器,数据变化后,很难保证数据的一致性。

结合以上优缺点,我们就会想到,如果有一种数据需要频繁访问,但一旦创建后就轻易不会改变,而且初始创建时就能预估占用的内存空间,那么这种类型的数据无疑是最适合用本地缓存存储了。

既然有了上述的应用场景,反观技术开发中的诉求,发现其实很多优秀的框架已经在这样使用了,比如缓存类class的反射信息,包括field、method等。因为class的数量是有限的,且内容不会轻易改变,在使用时无需再使用反射机制,而只需要从本地缓存读取数据即可。

分布式缓存的优缺点和应用场景

优势:

  • 数据集中存储,消除冗余数据,解决整体内存的占用率,易于维护集群建缓存数据的一致性。
  • 缓存中间件可以对缓存进行统一管理,便于水平扩容。

劣势:

  • 依赖分布式缓存中间件稳定性,一旦挂了,容易造成缓存雪崩;
  • 由于是跨机器获取缓存数据,因此会造成数据传输的网络消耗,以及一些序列化/反序列化的时间开销。

对于上述缺点中,网络耗时等开销是难免的,而且这些操作耗费的时间在可接受范围内,而对于中间件的稳定性则可以通过服务降级、限流或者多级缓存思路来保证。主要看中的是它的优点,既然分布式缓存天然能保证缓存一致性,那么我们倾向于将需要频繁访问却又经常变化的数据存放于此。

缓存框架使用过程的注意点

不论是本地缓存还是分布式缓存,在使用缓存提升性能的时候,必然会考虑缓存命中率的高低,考虑缓存数据的更新和删除策略,考虑数据一致性如何维护,本小节主要针对以上的问题来分析不同实现方案的优缺点。

缓存命中率

缓存命中率不仅是系统性能的一个侧面指标,也是优化缓存使用方案的一个重要依据。缓存命中率=请求命中数/请求总数。接下来的若干缓存使用策略所围绕的核心考量点就是在保证系统稳定性的同时,旨在提升缓存命中率。

缓存更新策略

主动请求DB数据,更新缓存

通过在集群中的每台机器都部署一套定时任务,每隔一段时间就主动向数据库DB请求最新数据,然后更新缓存。这样做的好处是可以避免缓存击穿的风险,在缓存失效前就主动请求加载DB数据,完成缓存数据更新的无缝连接。

但这样做也增加了机器的CPU和内存的占用率,因为即使有若干Key的缓存始终不被访问,可还是会被主动加载加载到内存中。也就是说,提高了业务抗风险能力,但对CPU和内存资源并不友好。

详情可参见下图,分布式缓存中存储着DB中的数据,每隔4.9s就会有定时任务执行去更新缓存,而缓存数据失效时间为5s,从而保证缓存中的数据永远存在,避免缓存击穿的风险。但对于Web请求来说,只会访问k1的缓存数据,也即对于k2和k3数据来说,是无效缓存。

被动请求DB数据,更新缓存

当有请求到达且发现缓存没数据时,就向DB请求最新数据并更新缓存。这种方案完全可以看做是方案一的互斥方案,它解决的是机器CPU和内存浪费的问题,内存中存储的数据始终是有用的,但却无法避免缓存失效的瞬间又突然流量峰值带来的缓存击穿问题,在业务上会有一定的风险。

详情见下图,缓存不会主动加载数据,而是根据Web请求懒加载数据。对于请求k1数据来说,发现缓存没有对应数据,到DB查询,然后放入Cache,这是常规流程;但如果有突发流量,大量请求同时访问k2数据,但Cache中没有数据时,请求就会同时落到DB上,可能压垮数据库。

缓存过期策略

依赖时间的过期策略

  • 定时删除

对于需要删除的每个Key都配备一个定时器,元素超时时间一到就删除元素,释放元素占用的内存,同时释放定时器自身资源。其优点是元素的删除很及时,但缺点也很明显,比如为每个Key配备定时器肯定会消耗CPU和内存资源,严重影响性能。这种策略只适合在小数据量且对过期时间又严格要求的场景能使用,一般生产环境都不会使用。

  • 惰性删除

元素过期后并不会立马删除,而是等到该元素的下一次操作(如:访问、更新等)才会判断是否过期,执行过期删除操作。这样的好处是节约CPU资源,因为只有当元素真的过期了,才会将其删除,而不用单独管理元素的生命周期。但其对内存不友好,因为如果若干已经过期的元素一直不被访问的话,那就会一直占用内存,造成内存泄漏。

  • 定期删除

以上两种元素删除策略各有优缺点,无非是对CPU友好,还是对内存友好。为了结合两者的优点,一方面减少了元素定时器的配备,只使用一个定时器来统一扫描过期元素;另一方面加速了判断元素过期的时间间隔,不是被动等待检测过期,而是间隔一段时间就主动执行元素过期检测任务。正是由于以上的改进点,此方案是元素过期检测的惯常手段。

我们假设一个场景,为了保护用户隐私,通常在用户电话和商家电话之间,会使用一个虚拟电话作为沟通的桥梁。业务使用中,往往同一个虚拟号码在一定时间内是可以对相同的用户和商家建立连接的,而当超出这个时间后,这个虚拟号码就不再维护映射关系了。

虚拟电话号码的资源是有限的,自然会想到创建一个虚拟号码资源池,管理虚拟号码的创建和释放。比如规定一个虚拟号码维持的关系每次能使用15分钟,那么过期后要释放虚拟号码,我们有什么方案呢?

A. 方案一:全量数据扫描,依次遍历判断过期时间

对于DB中存储的以上内容,每天记录都存储着虚拟号码的创建时间,以及经过expire_seconds就会删除此记录。那么需要配备一个定时任务扫描表中的所有记录,再判断current_time - create_time >expire_seconds,才会删除记录。

如果数据量很大的情况,就会导致数据删除延迟时间很长,这并不是可取的方案。那是否有方案能直接获取到需要过期的vr_phone,然后批量过期来解决上述痛点呢?来看看方案二吧。

B.方案二:存储绝对过期时间+BTree索引,批量获取过期的vr_phone列表

将相对过期时间expire_seconds改为记录过期的时间戳expire_timestamp,同时将其添加BTree索引提高检索效率。仍然使用一个定时器,在获取待删除vr_phone列表时只需要select vr_phone from table where now()>=expire_timestamp即可。

对于空间复杂度增加了一个BTree数据结构,而基于BTree来考虑时间复杂度的话,对于元素的新增、修改、删除、查询的平均时间复杂度都是O(logN)。

原文地址:https://www.cnblogs.com/winner192/p/11728858.html

时间: 2024-10-13 08:04:19

缓存技术使用的实践思考分析的相关文章

EDW on Hadoop(Hadoop上的数据仓库)技术选型和实践思考

在这篇文章中, 将讨论EDW on Hadoop 有哪些备选方案, 以及我个人的倾向性, 最后是建构方法.  欢迎转载, 但必须注明原贴(刘忠武,  http://www.cnblogs.com/harrychinese/p/edw_on_hadoop.html). 数据仓库发展已经有二十多年了, 我们先看看数据仓库发展的趋势: 在数据规模小的时候, 采用单节点RDBMS作为存储和执行引擎, 比如Oracle/PostgreSQL/MySQL都行; 当数据规模大了后, 或者时间窗口很紧时, 多采

如何正确使用缓存技术

缓存技术是用来提升程序运行性能的常见手段,如你所见, 阿里巴巴.新浪微博.美团网等互联网龙头企业都是用缓存技术来提升自己家网站的性能.然而,任何事物都有两面性, 缓存技术使用得当带来的好处自然不言而喻, 但是如果使用不当, 产生的副作用也够让人喝一壶的. 我们写服务器程序时,使用缓存的目的无非就是减少数据库访问次数降低数据库的压力和提升程序的响应时间, 然而根据具体的使用场景又可以派生出无数种情况, 比如说 程序频繁读取数据库, 但是查询获得的结果却总是相同的,这部分相同的结果是不是可以放入缓存

ASP.NET 缓存技术分析

缓存功能是大型网站设计一个很重要的部分.由数据库驱动的Web应用程序,如果需要改善其性能,最好的方法是使用缓存功能.可能的情况下尽量使用缓 存,从内存中返回数据的速度始终比去数据库查的速度快,因而可以大大提供应用程序的性能.毕竟现在内存非常便宜,用空间换取时间效率应该是非常划算的.尤 其是对耗时比较长的.需要建立网络链接的数据库查询操作等. 对于web页面的缓存,WebForm与ASP.NET MVC有不同的语法.在WebForm中, <%@ OutputCache Duration="6

兄弟连分析PHP缓存技术的多种方法小结

这里所说的数据缓存是指数据库查询PHP缓存机制,每次访问页面的时候,都会先检测相应的缓存数据是否存在,如果不存在,就连接数据库,得到数据,并把查询结果序列化后保存到文件中,以后同样的查询结果就直接从缓存表或文件中获得 1普通缓存技术 数据缓存:这里所说的数据缓存是指数据库查询PHP缓存机制,每次访问页面的时候,都会先检测相应的缓存数据是否存在,如果不存在,就连接数据库,得到数据,并把查询结果序列化后保存到文件中,以后同样的查询结果就直接从缓存表或文件中获得.用的最广的例子看Discuz的搜索功能

前端缓存技术一:使用ETags减少Web应用带宽和负载

介绍 最近,大众对于REST风格应用架构表现出强烈兴趣,这表明Web的优雅设计开始受到人们的注意.现在,我们逐渐理解了"3W架构(Architecture of the World Wide Web)"内在所蕴含的可伸缩性和弹性,并进一步探索运用其范式的方法.本文中,我们将探究一个可被Web开发者利用的.鲜为人知的工具,不引人注意的"ETag响应头(ETag Response Header)",以及如何将它集成进基于Spring和Hibernate的动态Web应用,

【华为云技术分享】根因分析

1.  什么是根因分析 在工作中我们经常会遇到根因分析的提法,有时也称作根原因分析或简称RCA(Root Cause Analysis),那什么是根因分析呢?目前还没有一个公认的定义,一般都是从操作层面来解释怎么进行根因分析的,缺少方法论框架性说明.有些书籍将发现问题和寻找解决方案也纳入根因分析的范围,使什么是根因分析变得更模糊.本文通过梳理相关知识,完善概念和模型,希望能在思维方法层面提供一个理解根因分析的新视角. 做为思维方法论,会涉及大量抽象概念和逻辑方法,本文把容易混淆的概念重新定义,而

强大的Spring缓存技术(上)

缓存是实际工作中非常常用的一种提高性能的方法, 我们会在许多场景下来使用缓存. 本文通过一个简单的例子进行展开,通过对比我们原来的自定义缓存和 spring 的基于注释的 cache 配置方法,展现了 spring cache 的强大之处,然后介绍了其基本的原理,扩展点和使用场景的限制.通过阅读本文,你应该可以短时间内掌握 spring 带来的强大缓存技术,在很少的配置下即可给既有代码提供缓存能力. 概述 Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)

redis 缓存技术与memcache的最大区别

1 什么是redis redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合)和zset(有序集合).这些数据类型都支持push/pop.add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的.在此基础上,redis支持各种不同方式的排序.与memcached一样,为了保证效率,数据都是缓存在内存中.区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写

.net环境下的缓存技术-转载!

摘要: 介绍缓存的基本概念和常用的缓存技术,给出了各种技术的实现机制的简单介绍和适用范围说明,以及设计缓存方案应该考虑的问题(共17页) 1         概念 1.1   缓存能解决的问题 · 性能--将相应数据存储起来以避免数据的重复创建.处理和传输,可有效提高性能.比如将不改变的数据缓存起来,例如国家列表等,这样能明显提高web程序的反应速度: · 稳定性--同一个应用中,对同一数据.逻辑功能和用户界面的多次请求时经常发生的.当用户基数很大时,如果每次请求都进行处理,消耗的资源是很大的浪