展开
湖北国联计算机科技有限公司
  • 首页HOME
  • 公司简介INTRODUCTION
  • 安全防御DEFENSE
  • 软件开发SOFTWARE
  • 物联网IOT
  • 运行维护SRE
  • 成功案例CASE
  • 联系我们CONTACT
  • SOFTWARE |软件开发

    后台开发必备:每个程序员都应掌握的缓存技术
    来源:湖北国菱计算机科技有限公司-湖北国联计算机科技有限公司-荆州网站建设-荆州软件开发-政府网站建设公司 时间:2025-03-25

    缓存(Cache)是一种存储技术,可以存储数据,以便快速获取数据。缓存最重要的是两个特性:存储、快速获取。缓存的本质:「用空间换时间」,用快速存储的介质保存数据,以提升数据访问的速度。
    在计算机的世界里,缓存被广泛应用于硬件(如CPU 高速缓存、寄存器)和软件中(如浏览器缓存、CDN、应用程序中的缓存等)。
    后台中的缓存
    后台开发中,缓存的使用场景一般有:

    ü 提升接口响应速度:缓存相比IO 请求、数据库查询速度要快得多,适当使用缓存提升响应速度

    ü 降低数据源服务的负载压力:将需要高并发读取的数据缓存起来,当相同请求进来时返回缓存数据,减轻数据源服务(如数据库、上游系统)的负载压力

    ü 减少计算资源的浪费:将需要复杂且耗时计算的结果缓存起来,减少相同请求导致的重复计算资源浪费

    01

    缓存策略

    缓存策略通常分为两种,通读缓存和旁路缓存。

    1.1 通读(read-through)缓存

    在使用通读缓存时,应用程序会尝试从缓存中获取数据。如果该数据已存在于缓存中,那么缓存会直接返回该数据。若缓存中并未包含所需数据,那么缓存会自行访问数据源来获取数据,并将获取的数据返回给应用程序,同时将这份数据保存在缓存中。如此一来,当应用程序下次需要同样的数据时,就能够直接从read-through 缓存中获取无需再次访问数据源。

    通读缓存的应用有很多,比如CDN:
    CDN(Content Delivery Network)即内容分发网络,是一种分布式的网络架构。依赖于服务商提供的广泛分布于各地的 CDN 服务器,通过把数据分发并缓存到各地的 CDN 服务器上,当用户请求数据时,CDN 会匹配离用户距离最近的节点并返回缓存数据,以此来提高用户访问资源的速度。CDN 一般用来加速静态资源的传输,比如图片、CSS、HTML 等内容。而动态的内容,如搜索结果、单据信息等则不合适,

    这类数据需要应用服务器实时计算后才能返回。

    1.2 旁路(cache-aside)缓存


    与通读缓存不同,旁路缓存不直接与数据源打交道。应用程序尝试从旁路缓存获取数据,如果数据不存在,则返回空。应用程序自行请求数据源获取数据,并写入旁路缓存。这样下次相同的请求到达时,应用程序从旁路缓存中则会获取到数据。


    通读缓存和旁路缓存这两种策略,一般来说都会灵活应用、互相包含。比如通读缓存中,对数据的查询和写缓存,使用的就是旁路缓存策略。而该实现被整体封装起来,对外表现的则是通读缓存策略。

    02


    缓存类型
    在后台服务中,缓存的类型可以分为本地缓存和分布式缓存。
    2.1 本地缓存(local cache)
    本地缓存,与应用程序的进程有相同的生命周期,存放于应用程序的堆空间(heap)中。

    ü 优势:使用简单;无外部依赖;读取速度快(无网络IO 请求);

    ü 缺点:空间小:应用程序的服务器资源有限,所以本地缓存的空间小;分布式一致性问题:如果后台服务是分布式架构的,那么不同的服务实例之间的本地缓存可能会有差异;无法持久化:本地缓存会随着进程结束而被销毁,无法持久化。


    2.2 分布式缓存(remote cache)
    分布式缓存,也可理解为远端缓存。使用外部的缓存服务,独立部署,与应用程序解藕。

    ü 优势:空间充足:外部存储一般空间都很充足;无分布式一致性问题:不同的服务实例连接同一个缓存服务,不存在一致性问题;主流的分布式缓存,如redis,支持数据持久化和恢复,当缓存服务挂了可以恢复数据。

    ü 缺点:引入外部依赖、需要部署和运维单独的缓存服务。
    2.2.1 常见的缓存服务
    Redis

    ü 支持多种数据结构,如:list,set,zset,hash 等数据结构。

    ü 支持数据的持久化和恢复。

    ü 支持多种集群模式:主从复制、哨兵模式和Cluster 模式,保证高可用、容灾恢复、易于扩展。

    ü 能提供毫秒级别的响应速度。

    ü Redis 6.0 引入了多线程 IO,之前是单线程模型。
    Memcache

    ü 主要支持简单的键值对存储。

    ü 不支持持久化和恢复。

    ü 集群:可以通过客户端分片实现分布式存储。

    ü 多线程,非阻塞IO 模式。

    ü 能提供毫秒级别的响应速度。


    选择Redis 还是 Memcached 取决于具体的应用需求。如果需要一个轻量级、专注于缓存的解决方案,且不需要复杂的数据类型和持久化,Memcached 可能是更合适的选择。而如果应用需要利用丰富的数据类型、持久化以及构建高可用的分布式系统,Redis 将是更强大、更灵活的选择。

    03


    缓存淘汰策略
    由于缓存的空间是有限的,如果缓慢的空间被使用完了,则需要淘汰旧的数据,腾出空间给新的数据使用。缓存淘汰常用的几种策略有如下几种。
    3.1 FIFO(First In First Out)算法
    FIFO 算法是最简单最好理解的,其策略是:先进先出,如果一个数据的写入时间越早,说明将来被访问的几率越低。因此 FIFO 算法优先淘汰最早写入的数据。

    3.2 LRU(Least Recently Used)算法
    LRU 算法,即最近最少使用算法。如果一个数据最近被访问了,那么将来被访问的几率越高。反之,如果一个数据很久都没有访问,那么将来被访问的几率越低。其淘汰策略就是:优先淘汰最久没有被使用到的数据。LRU 通常使用双向链表+哈希表来实现。

    3.3 LFU(Least Frequently Used)算法
    LFU 算法,即最少使用算法。如果一个数据被访问的次数越多,那么将来被访问的几率越高。反之,如果一个数据被访问的次数越少,那么将来被访问的几率越小。其淘汰策略就是:优先淘汰最少被使用的数据。LFU 算法可以使用小顶堆+哈希表来实现。


    大部分本地缓存的三方库或缓存服务,都支持设置淘汰算法,无需自行实现。

    04


    缓存常见问题
    4.1 缓存与数据源的一致性
    缓存的数据是来自数据源的,当数据源被更新了,而缓存没有被更新,后台服务则会从缓存中取到脏数据,这就有数据脏读的问题。对于这个问题,主要的策略有两种。
    4.1.1 过期失效
    每个写入缓存中的数据,都设置一个合适的过期时间,在有效期内都返回缓存的数据。当缓存数据过期失效,则会回源到数据源,重新缓存最新的数据。这种情况会有数据脏读的问题,不过采用过期失效的数据,一般是更新不频繁的数据,比如用户信息、热门信息等,存在一定的数据延迟是可以接受的。
    4.1.2 主动更新
    当数据源的数据更新了,程序主动去更新缓存数据,保证缓存中的数据始终是最新的。这种策略,适合对数据的时效性要求很高的数据,比如库存、余额等等。主动更新的代价则是代码的复杂度增加,所有涉及数据更新的操作,都需要更新其缓存数据。
    无论是过期失效还是主动更新,首先应该分析当前场景对数据的时效性要求是否很高?如不是,过期失效足矣。如果是,需要衡量主动更新的代价能否接受,比如代码复杂度增加。否则是否可以通过缩短失效时间而采取过期失效策略来折中处理。
    4.2 缓存雪崩
    缓存雪崩是指在同一时间点后台服务中的缓存大量过期失效,当服务的并发量很高时,大量的数据请求同时到达数据源服务(比如数据库或其他服务),引起数据源服务的瞬时负载增大,甚至崩溃。
    引起缓存雪崩的原因一般有两种:

    ü 一是大量的缓存key 在同一时间失效

    ü 二是缓存服务不可用,请求都被透传到数据库。



    解决办法:

    ü 设置合理的缓存失效时间:合理设置过期时间,分散缓存的失效时间,避免缓存在同一时间失效。

    ü 保证缓存服务的高可用:使用独立的缓存服务,尽量使用缓存集群,保证缓存服务的高可用和容灾恢复。

    4.3 缓存穿透
    缓存穿透是指同一时间大量的空值请求到达后台服务,空值请求是指查询数据源后无数据的请求,由于数据源返回空数据,所以缓存层没有将空值保存,导致空值请求必然会穿透缓存层,透传到数据源。
    引起缓存穿透的原因,一般有:

    ü 未对请求参数进行合理的校验和拦截。

    ü 被精心构造的恶意请求攻击。


            解决办法:

    ü 设置合理的参数校验:通过设置合理的校验规则,比如id 范围、名称正则规则等,对不合理或空值请求的参数的进行过滤和拦截。

    ü 缓存空值处理:即使数据源返回空值,也在缓存层将其保存起来。可能对其数值设置一些标记,比如value=-1 等等,方便服务识别为空值。同时,也可以为空值的缓存设置一个较短的失效时间。
    4.4 缓存击穿
    缓存击穿是指某个热点数据的缓存失效了,然后同一时间有大量的请求访问该热点数据,由于缓存失效,这些请求同时被透传到数据源服务,导致数据源的负载增加,甚至崩溃。
    引起缓存击穿的原因,一般是:热点数据的缓存失效时,高并发请求同时访问该数据。


    解决办法:

    ü 使用互斥锁或者分布式锁,对数据的回源操作进行上锁,保证同一时刻只有一个请求被透传到数据源服务。

    ü 热点数据的缓存永不过期,由数据源主动更新缓存。

    ü 热点数据预加载:在缓存数据将要过期时,由后台服务主动更新热点数据缓存,防止缓存失效。

    05

    总结
    本文详细地介绍了后台开发中的缓存技术,希望能对你的日常工作有所帮助和启发。熟练掌握各种缓存策略和机制,解决缓存问题,对于程序员而言至关重要,可以在很大程度上提升后台开发的效率、稳定性和用户体验。


    荆州地区政府网站建设 解决方案 专业团队 腾讯第三方平台 地址:湖北省荆州市沙市区荆沙大道楚天都市佳园一期C区29栋112       地址:湖北省松滋市新江口街道才知文化广场1幢1146-1151室     邮编:434200 联系电话:0716-6666211     网站编辑部邮箱:business@gl-ns.com 鄂公网安备 42100202000212号 备案号:鄂ICP备2021015094号-1     企业名称:湖北国菱计算机科技有限公司