缓存设计:做好缓存设计的关键是什么?

简介: 缓存设计:做好缓存设计的关键是什么?

缓存乃是一个用于临时存储数据的所在。当用户进行数据查询时,第一步便是在缓存中探寻,倘若找到了,便直接加以运用;要是未找到,就需前往数据的初始位置寻觅。因而,缓存实质上属于一种以空间换取时间的技术手段,借由数据在空间层面的重复,来加快数据的访问速度。

不过,伴随分布式以及云计算技术的不断发展,数据存储技术已然发生了天翻地覆般的变化。而且,不同的存储技术在价格和性能方面均存在极大的差异。所以,在针对性能展开软件设计的时候,如果我们未能做好多层级的缓存设计,不但有可能造成金钱的浪费,而且所获取的性能收益或许也难以达到理想状态。

缓存设计的通关之路

那么首先,我打算从两个问题入手,引领您了解缓存设计应在何时开展,以及通过对不同数据类型特性的对比分析,和您共同探讨怎样才能做好缓存设计。

好,第一个问题:在互联网应用服务中,运用缓存技术的目的难道仅仅是为了提升访问速度吗?实际上,我觉得并非所有的缓存都只是为了提速,因为在分布式系统里,缓存机制实则是系统级性能设计的一项重要权衡手段。例如,当某个数据库的负载较高,接近系统瓶颈时,我们能够运用缓存技术,将负荷分摊至其他数据库中,在此,使用缓存的目的,主要是实现负载均衡,而非提升访问速度。

第二个问题:一个大型系统中的数据种类繁多,那么是否需要为每种数据都规划缓存机制呢?其实完全没必要。在实际的业务场景中,系统所包含的业务数据极多,您不可能针对每种数据都去设计和实现缓存机制,一方面是投入的软件成本过高,另一方面也很可能无法带来较高的性能收益。所以,在开展缓存设计之前,您首先需要辨别出哪些数据访问对性能的影响较大。那么我们应当如何去辨别哪些数据需要缓存机制呢?

不过接下来,在识别出需要运用缓存机制的数据之后,您或许会发现,这些数据种类之间的特性差异极大,如果采用同一种缓存设计,实际上很难让软件性能达到最佳状态。所以在此,我为您总结了三种需要缓存机制的数据种类,分别是不变性数据、弱一致性数据、强一致性数据。了解这三种缓存数据种类的差异,以及对应的设计缓存机制的方法,您就掌握了缓存设计的核心要义。

好,下面我们就来具体了解下吧。

首先是不变性数据。不变性数据意味着数据永远不会发生变化,或者在相当长的一段时间内不会发生变化,所以我们也能够认定这部分数据是不变的。此类数据属于可以优先考虑运用缓存技术的一种数据类型,在实际的业务场景中数量众多。例如,Web 服务里的静态网页、静态资源,或者数据库表中列数据与 key 的映射关系、业务的启动配置等等,这些都能够被视为不变性数据。

而且,不变性数据还意味着实现分布式一致性会极为容易,我们能够为这些数据任选数据存储方式,也能够任选存储节点位置。故而,我们实现缓存机制的方式能够十分灵活,也会相对简单。比如在 Java 语言中,您可以直接使用内存 Caffeine,或者内置的结构体当作缓存均可。

另外这里需要您注意,当您针对不变性数据进行缓存设计时,其中的缓存失效机制可以采用永远不失效,或者基于时间的失效方式。而在采用基于时间的失效方式时,您还需要依据具体的业务需求,在缓存容量和访问速度之间做好设计实现方面的权衡。

弱一致性数据

第二种是弱一致性数据。它表示数据经常会发生变化,然而业务对于数据的一致性要求并不高,也就是说,不同用户在同一时间点看到并非完全一致的数据,都是能够被接受的。鉴于这类数据对一致性的要求相对较低,所以在设计缓存机制时,您只需达成最终一致性即可。这类数据在实际业务里也较为常见,例如业务的历史分析数据、一些搜索查找返回的数据等,即便最近的部分数据未被记录进去,影响也不大。

另外,快速辨别这类数据还有一个办法,那便是使用从数据库 Replica(复制)节点中读取的数据,其中大部分都属于这种类型的数据(很多数据库 Replica 节点的数据由于数据同步存在时延,是不满足强一致性要求的)。针对弱一致性的数据,我们通常采用的缓存失效机制是基于时间的失效方式,同时由于弱一致性的特点,您能够较为灵活地选择数据存储技术,比如内存 Cache,或者是分布式数据库 Cache。您甚至能够基于负载均衡的调度,来设计多层级缓存机制。

强一致性数据

第三种缓存数据类型是强一致性数据。其指的是数据会频繁发生变化,并且业务对数据库的一致性要求极高,也就是说当数据产生变更后,其他用户在系统内的任何地方,都应当看到的是更新后的数据。

那么,对于这种类型的数据,我通常不建议您使用缓存机制,因为这类数据运用缓存会较为复杂,并且极易引入新的问题。例如,用户能够直接提交和修改的各类数据内容,如果未同步修改缓存中的数据,就会引发数据不一致性的问题,导致较为严重的业务故障。

不过在某些特殊的业务场景中,比如,在个别数据访问频率极高的情况下,我们依旧需要通过设计缓存机制,来进一步提高性能。

因此针对这类强一致性数据,在设计缓存机制时,您需要尤其留意两点:

这种数据的缓存必须采用修改同步的实现方式。也就是说,所有的数据修改都必须保证能够同步修改缓存与数据库中的数据。

精确识别特定业务流程中,能够使用缓存获取数据的时长。因为有些缓存数据(比如一次 REST 请求中,多个流程都需要使用的数据)只能够在单次业务流程中使用,不能跨业务流程使用。

好了,以上便是三种典型的数据种类的缓存设计思路了。

这里您需要注意的是,使用缓存必定是以性能优化为目的,因此,您还需要运用评估模型来分析缓存是否达成了性能优化的目标。

那么具体是何种评估模型呢?我们来看一下这个性能评估模型的公式:AMAT = Thit + MR * MP。其中:AMAT(Average Memory Access Time),代表的是平均内存访问时间;Thit,指的是命中缓存之后的数据访问时间;MR,是访问缓存的失效率;MP,是指缓存失效后,系统访问缓存的时间与访问原始数据请求的时间之和。

另外这里您可能会留意到,AMAT 与原始数据访问之间的差值,代表的就是使用缓存所带来的访问速度的提升。而在一些缓存使用不当的场景下,增加的缓存机制很可能会造成数据访问速度下降的情况。所以接下来,我就通过真实的缓存设计案例,来引领您理解如何正确地使用缓存,以此助力您更有效地提升系统性能。

缓存设计的典型使用场景

好,在开始介绍之前呢,我还想为您说明一下,在真实的业务里,缓存设计的场景实际上有很多,在这里我的目的主要是让您明晰缓存设计的方法。

因此,我会从两个较为典型的案例场景着手,引领您理解缓存的运用。

如何做好静态页面的缓存设计?

在 Web 应用服务中,一个重要的应用场景便是静态页面的缓存使用。这里所说的静态页面,指的是在一个网站内,所有用户看到的都是相同的页面,除非重新部署,否则通常不会发生变更,比如大部分公司官网的首页封面等等。通常情况下,静态页面的访问并发量是比较大的,如果您不运用缓存技术,不但会导致用户响应时延较长,而且会给后端服务带来极大的负载压力。

那么针对静态页面,我们在使用缓存技术时,可以通过将静态缓存放置在距离用户较近的位置,来降低页面数据在网络上的传输时延。

现在,我们来看一个针对静态页面使用缓存设计的示意图:

图片

如图上所示,针对静态网页,首先您就能够在软件后端服务的实例中运用缓存技术,以此避免每次都要重新生成页面信息。然后,由于静态网页属于不变性数据,所以您可以使用内存或文件级缓存。

另外,针对访问量极大的静态页面,为了更进一步减轻对后端服务的压力,您还能够将静态页面置于网关处,接着利用 OpenResty 等第三方框架增添缓存机制,以保存静态页面。

除此之外,在网页中众多的静态页面或静态资源文件,还需要使用浏览器的缓存,来进一步提高性能。注意,这里我并非是建议您针对所有的静态页面,都需要设计三层的缓存机制,而是您要知晓,在软件设计阶段,通常就需要考虑如何进行静态页面的缓存设计了

后端服务如何设计数据库的多级缓存机制?

还有一个典型的缓存场景是针对数据库的缓存。现在的数据库通常都是分布式存储的,而且规模都比较大,在针对大规模数据进行查询与分析计算时,都需要花费一定的时间周期。因此,我们可以先识别出这些计算结果中可以使用缓存机制的数据,然后就可以使用缓存来提升访问速度了。下面是一张针对数据库缓存机制的原理图:

图片

从图上能够看到,内存级 Cache、分布式 Cache 均可充当数据计算分析结果的缓存。而且,不同级别的缓存访问速度存在差异,内存级的 Cache 访问速度能够达到微秒级别,甚至更优;分布式 Cache 访问速度通常小于毫秒级别;而对于原生数据库的查询与分析,通常大于毫秒级别。

因此,在具体规划缓存机制的时候,您就需要依照前面我所介绍的缓存使用原理,辨别出数据类型,进而选择并设计缓存实现机制。

另外,在通过缓存机制实现访问速度优化的过程中,我们主要关注的是不同层级缓存所带来的访问速度提升,并且在此处,不同层级缓存也能够存在于一个数据库中。

比如,在我参与设计的一个性能优化项目里,其 Cache 策略便是,使用 MongoDB 中的另外一个 Collection(集合),作为缓存查询分析,以此来优化性能。所以,您在进行缓存设计时,关注点应当置于不同的数据种类,以及不同层级缓存的性能评估模型上,而非仅仅关注数据库。只有如此,您才能够设计出更出色、更优良的性能缓存方案。

相关文章
|
6月前
|
缓存 应用服务中间件 数据库
【分布式技术专题】「缓存解决方案」一文带领你好好认识一下企业级别的缓存技术解决方案的运作原理和开发实战(多级缓存设计分析)
【分布式技术专题】「缓存解决方案」一文带领你好好认识一下企业级别的缓存技术解决方案的运作原理和开发实战(多级缓存设计分析)
145 1
|
存储 缓存 NoSQL
微服务实践01--微服务管理11--缓存02--分级缓存设计
微服务实践01--微服务管理11--缓存02--分级缓存设计
322 0
微服务实践01--微服务管理11--缓存02--分级缓存设计
|
存储 SQL 缓存
走进缓存的世界(二) - 缓存设计
系列文章 走进缓存的世界(一) - 开篇 走进缓存的世界(二) - 缓存设计 走进缓存的世界(三) - Memcache   如何设计缓存 主要考虑三个问题: 缓存哪些数据 如何缓存 如何保证数据一致性 缓存哪些数据  系统优化时有一句话必须切记:“优化无止境”,所以如果缓存不是必须的,请果断去掉,要知道越是业务上复杂的系统,对Cache的使用反而越简单,因为对于一个复杂、多变、历史悠久的系统,在Cache方面做过度设计会让人深陷其中;缓存的数据越多,系统的维护成本就越高,所以找准需要缓存的点尤为重要。
1032 0
|
设计模式 存储 缓存
面试必问的缓存使用:如何保证数据一致性、缓存设计模式
缓存使用在现在的项目中非常常见,缓存在为我们带来便利的同时,也会带来一些常见的问题,如果不谨慎使用,可能会带来意想不到的结果。
533 0
面试必问的缓存使用:如何保证数据一致性、缓存设计模式
|
Web App开发 XML 缓存
一起谈.NET技术,.Net下的分布式缓存--从Discuz!NT的缓存设计谈起
  最近拜读了代振军同学写的关于Discuz!NT的缓存设计的一篇文章《Discuz!NT 缓存设计简析 [原创]》,颇有些想法,姑且写在这里让大家拍砖吧。   缓存真是个好东西,在大型的系统中可以有效地提升系统的速度,此乃废话就不多说了,在.
1229 0
|
26天前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(一)
数据的存储--Redis缓存存储(一)
60 1
|
26天前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(二)
数据的存储--Redis缓存存储(二)
37 2
数据的存储--Redis缓存存储(二)
|
22天前
|
消息中间件 缓存 NoSQL
Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。
【10月更文挑战第4天】Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。随着数据增长,有时需要将 Redis 数据导出以进行分析、备份或迁移。本文详细介绍几种导出方法:1)使用 Redis 命令与重定向;2)利用 Redis 的 RDB 和 AOF 持久化功能;3)借助第三方工具如 `redis-dump`。每种方法均附有示例代码,帮助你轻松完成数据导出任务。无论数据量大小,总有一款适合你。
56 6
|
27天前
|
缓存 NoSQL 关系型数据库
redis和缓存及相关问题和解决办法 什么是缓存预热、缓存穿透、缓存雪崩、缓存击穿
本文深入探讨了Redis缓存的相关知识,包括缓存的概念、使用场景、可能出现的问题(缓存预热、缓存穿透、缓存雪崩、缓存击穿)及其解决方案。
127 0
redis和缓存及相关问题和解决办法 什么是缓存预热、缓存穿透、缓存雪崩、缓存击穿
|
2天前
|
存储 缓存 监控
利用 Redis 缓存特性避免缓存穿透的策略与方法
【10月更文挑战第23天】通过以上对利用 Redis 缓存特性避免缓存穿透的详细阐述,我们对这一策略有了更深入的理解。在实际应用中,我们需要根据具体情况灵活运用这些方法,并结合其他技术手段,共同保障系统的稳定和高效运行。同时,要不断关注 Redis 缓存特性的发展和变化,及时调整策略,以应对不断出现的新挑战。
21 10