缓存为王:老码农眼中的分布式缓存


本文来自作者 老曹  GitChat 上分享 「缓存为王:老码农眼中的分布式缓存」,阅读原文查看交流实录。

文末高能

编辑 | 哈比

世界是相似的,在商业的世界中,有一句经典语录叫 “现金为王”。在互联网乃至整个软件技术世界中,与之对应的一个说法就是 “缓存为王”。

什么是缓存呢?维基百科给出的解释是:

Cache: a collection of data duplicating original values stored elsewhere on a computer, usually for easier access.

简单的讲,缓存是系统快速响应中的一种关键技术,是一组被保存起来以备将来使用的东西,介于应用开发和系统开发之间,是产品经理们经常顾及不到的地方,满足技术架构设计中的非功能性约束。

由于缓存是王者,“普天之下,莫非王土 “,人们对王者的认识又往往一叶障目。

例如,CPU 的缓存是指位于 CPU 与内存之间的临时存储器,容量比内存小但交换速度又比内存要快得多。

由于 CPU 的运算速度要比内存读写速度快,CPU 总有等待数据的时候,而高速缓存则解决了 CPU 运算速度与内存读写速度不匹配的矛盾。而且,CPU 是有多级缓存的,有时候也称为几级流水。

计算机硬件上就使用了缓存,操作系统层面也是如此。在编程的时候,包括 CPU 接触到的都是虚拟地址而不是真实的物理地址,这是虚拟内存的一大主要功能,也可以理解成缓存。

因此,缓存与语境有着紧密的关系,缓存在不同场景有着不同的意义,采用的技术手段也是不同的。

不涉及操作系统和硬件的缓存,根据缓存在软件系统中所处位置的不同,大体可以分为三类:

  • 客户端侧的缓存;

  • 服务器侧的缓存;

  • 网络中的缓存。

根据缓存的规模和部署方式又可以分为:

  • 单体缓存;

  • 缓存集群;

  • 分布式缓存。

在软件系统中缓存几乎无处不在,这或许就是缓存为王的一个原因吧。

为什么使用缓存?

在看这个问题之前,可以先看一下成功的软件产品具备哪些特点:

  • 能解决目标用户的痛点;

  • 能够为企业或个人带来利益;

  • 具有不错的用户粘性。

其中一个极其重要的因素就是要有好的用户体验。

那什么是用户体验么?

人们对于针对使用或期望使用的产品、系统或者服务的认知印象和回应。

——《ISO 9241-210》

用户体验,即用户在使用一个产品或系统之前、使用期间和使用之后的全部感受,包括情感、信仰、喜好、认知印象、生理和心理反应、行为和成就等各个方面。

有许多因素可以影响用户体验,这些因素被分为三大类:使用者的状态,系统性能,以及环境。其中系统性能是软件产品自身对用户体验的关键性因素之一。

由于感受软件性能的主体是人,不同的人对于同样的软件能有不同的主观感受,而且不同的人对于软件性能关心的视角也不同。系统性能是一种非功能特性,它关注的不是某种特定的功能,而是在完成该功能时所展示出来的及时性。

缓存为王 是为了性能至上

系统性能是用户体验的重要因素。如何度量系统性能呢?系统性能的指标一般包括:响应时间,延迟时间,吞吐量,并发用户数和资源利用率的几个方面。

浏览器到网络,到应用服务器,甚至到数据库,通过在各个层面应用缓存技术,整个系统的性能将大幅提高。

例如,缓存离客户端更近,从缓存请求内容比从源服务器所用时间更少,呈现速度更快,系统就显得更灵敏。

缓存数据的重复使用,大大降低了用户的带宽使用,其实也是一种变相的省钱(如果流量要付费的话),同时保证了带宽请求在一个低水平上,更容易维护。

所以,使用缓存技术,可以降低系统的响应时间,减少网络传输时间和应用延迟时间,进而提高了系统的吞吐量,增加了系统的并发用户数。

利用缓存还可以最小化系统的工作量,使用了缓存就可以不必反复从数据源中查找,缓存所创建或提供的同一条数据更好利用了系统的资源。

因此,缓存是系统调优时常用且行之有效的手段,无论是操作系统还是应用系统,缓存策略无处不在。

音乐是时间的艺术,那么,缓存就是软件系统中关于时间的艺术。“缓存为王” 本质上是系统性能为王,对用户而言就是用户体验为王。

简单回顾:从网站的架构发展看缓存

最初的网站很多就是一台物理主机,放在 IDC 或者主机托管,上面只运行着应用服务器和数据库,LAMP(Linux Apache Mysql Php)就是这样流行起来的。随着业务和用户的增长,开始分离数据层,如下图所示:

随着访问网站的人数越来越多,响应速度又开始变慢了,可能是访问数据库的操作太多,导致数据连接竞争激烈,因此缓存开始登场了。动静态分离,缓存同步 …… 一直到分布式缓存的应用。这时的大型网站架构是这样的:

至此,系统进入了无级缩放的大型网站阶段,当网站流量增加时,应对的解决方案就是不断的添加 web 服务器,数据库服务器,以及缓存服务器了。

简单回归一下网站架构的发展历程,业务量的增长是幸福的,但也有成长的烦恼,而缓存技术就是解除烦恼的灵丹妙药,能够再次理解为什么是缓存为王。

现在,从缓存在系统中的位置来看看这一王者在系统中各个层面的应用。

客户端缓存

客户端缓存相对于其他端的缓存而言,要简单一些,而且通常是和服务端以及网络侧的应用或缓存配合使用的。

对于互联网应用而言,也就是通常所说的 BS 架构应用,可以分为页面缓存和浏览器缓存。对于移动互联网应用而言,是指 APP 自身所使用的缓存。

页面缓存

前端页面缓存有两层含义,一个是页面自身对某些页面元素或全部元素进行缓存,另一层意思是服务端将静态页面或动态页面的元素进行缓存,然后给客户端使用。这里的页面缓存指的是页面自身的缓存或者离线应用缓存。

页面缓存是将之前渲染的页面保存为文件,当用户再次访问时可以避开网络连接,从而减少负载,提升了性能和用户体验。

随着单页面应用(Single Page Application,SPA)的广泛使用,而且 HTML5 支持了离线缓存和本地存储,大部分 BS 应用的页面缓存都可以举重若轻了。

在 HTML5 中使用本地方法也很简单,示例代码如下:

localStorage.setItem("mykey","myvalue") localStorage.getItem("mykey","myvalue") localStorage.removeItem("mykey") localStorage.clear()

HTML5 提供的离线应用缓存机制,使得网页应用可以离线使用,这种机制在浏览器上支持度非常广,可以放心的使用该特性来加速页面的访问。开启离线缓存的步骤如下:

需要注意的是:manifest 文件中列出的资源 url 必须和 manifest 本身使用同样的网络协议,详情参考 W3C 相关的标准文档。

浏览器缓存

浏览器缓存是根据一套与服务器约定的规则进行工作的,工作规则很简单:检查以确保副本是最新的,通常只要一次会话。浏览器会在硬盘上专门开辟一个空间来存储资源副本作为缓存。在用户触发 “后退” 操作或点击一个之前看过的链接的时候,浏览器缓存会很管用。

同样,如果访问系统中的同一张图片,该图片可以从浏览器缓存中调出并几乎立即显现出来。

Http 1.1 有了较大的增强,缓存系统被形式化了,引入了实体标签 e-tag。e-tag 是文件或对象的唯一标识 , 这意味着可以请求一个资源 , 以及提供所持有的文件,然后询问服务器这个文件是否有变化。如果某一个文件的 e-tag 是有效的,服务器会生成 304-Not Modified 应答,并提供正确文件的 e-tag,否则,发送 200-OK 应答。

以 Web 浏览器使用 e-tag 为例,如图所示:

浏览器缓存能够极大地提升终端用户的用户体验,那么,用户在使用浏览器的时候,会有各种操作,如输入地址后回车,按 F5 刷新等等。

app 上的缓存

无论大型或小型 APP,灵活的缓存不仅大大减轻了服务器的压力,而且因为更快速的用户体验而方便了用户。

如何把 APP 缓存对于业务组件透明,以及 APP 缓存数据的及时更新,是 APP 缓存能否成功应用起来的关键。

APP 将内容缓存在内存,文件,或本地数据库(例如 Sqlite)中,但基于内存的缓存要谨慎使用。

对于 APP 中的某些界面,可以采用文件缓存方法。这种方法使用文件操作的相关 API 得到文件的最后修改时间,与当前时间判断是否过期,从而实现缓存效果,操作简单,代价较低。

需要注意的是,不同类型文件的缓存时间不一样。例如,图片文件的内容是相对不变的,直到最终被清理掉,APP 可以永远读取缓存中的图片内容。 而配置文件中内容是可能更新的,需要设置一个可接受的缓存时间。

 同时,不同环境下的缓存时间标准也是不一样的,WiFi 网络环境下,缓存时间可以设置短一点,一是网速较快,二是流量不要钱。而移动数据流量环境下,缓存时间可以设置长一点,节省流量,而且用户体验也更好。

不论是哪个移动平台,都有很多强大的库可以支持 APP 上的缓存,例如 iOS 上的 SDWebImage 等。

网络侧缓存

网络侧的缓存位于客户端和服务端之间,代理或响应客户端的网络请求,从而对重复的请求返回缓存中的数据资源。同时,接受服务端的请求,更新缓存中的内容。

Web 代理

Web 代理几乎是伴随着联网诞生的,常用的 Web 代理分为正向代理、反向代理和透明代理。Web 代理缓存是将 web 代理作为缓存的一种技术。一般情况下,Web 代理默认说的是正向代理,如图所示:

当通过代理服务器进行网络访问,浏览器不是直接到 Web 服务器去取回网页而是向 Web 代理发出请求,由代理服务器来取回浏览器所需要的信息并传送给浏览器。 

而且,Web 代理缓存有很大的存储空间,不断将新获取得数据储存到本地的存储器上,如果浏览器所请求的数据在 Web 代理的缓存上已经存在而且是最新的,那么就不重新从 Web 服务器取数据,而是直接将缓存的数据传送给用户的浏览器,这样就能显著提高浏览速度和效率。

对于企业而言,使用 Web 代理即可以节省成本,又能提高性能。

对于 Web 代理缓存而言,较流行的是 Squid,它支持建立复杂缓存层级结构的能力,拥有详细的日志、高性能缓存以及用户认证支持。

Squid 同时支持各种插件,例如,Squid Guard 就是一个提供 URL 过滤的插件,对于屏蔽某些站点和内容十分有用。

如果需要分析 Squid 的各种指标,webalizer 应该是个不错的选择。

边缘缓存

使用 Web 反向代理服务器和使用正向代理服务器一样,可以拥有缓存的作用,反向代理缓存可以缓存原始资源服务器的资源,而不是每次都要向原始资源服务器请求数据,特别是一些静态的数据。

比如图片和文件,很多 web 服务器就具备反向代理的功能,比如大名鼎鼎的 Nginx。

如果这些反向代理服务器能够做到和用户来自同一个网络,那么用户访问反向代理服务器,就会得到很高质量的响应速度,所以可以将这样的反向代理缓存称为边缘缓存。

边缘缓存在网络上位于靠近用户的一侧,可以处理来自不同用户的请求,主要用于向用户提供静态的内容,以减少应用服务器的介入。边缘缓存的一个有名的开源工具就是 varnish,在默认情况下进行保守缓存。

也就是说,varnish 只缓存它所知的安全内容。varnish 的一个特性是使用虚拟内存,精妙之处在于利用了操作系统的管理机制。varnish 可以高度定制如何处理请求,缓存哪些内容。

边缘缓存中典型的商业化服务就是 CDN 了,例如 AWS 的 Cloud Front,我国的 ChinaCache 等,现在一般的公有云服务商都提高了 CDN 服务。CDN 是 Content Delivery Network 的简称,即 “内容分发网络” 的意思。

使用 CDN 之后,客户端与服务器通信如图所示:

CDN 服务商一般会提供基于文件后缀、目录等多个维度来指定在 CDN 上的缓存时间,为用户提供更精细化的缓存管理。CDN 上的缓存时间会对 “回源率” 产生直接的影响。

若数据在 CDN 上的缓存时间较短,则 CDN 边缘节点上的数据会经常失效,导致频繁回源,增加了源站的负载,同时也增大了访问延时;

若数据 CDN 上的缓存时间太长,会带来数据更新时间慢的问题。开发者需要针对各自特定的业务,来做特定的数据缓存时间管理。

一般地,CDN 边缘节点对开发者来说是透明的,开发者可以通过 CDN 服务商提供的 “刷新缓存” 接口来清理位于 CDN 边缘节点上的缓存数据。

这样开发者在更新数据后,可以使用 “刷新缓存” 功能来强制要求 CDN 边缘节点上的数据缓存过期,保证客户端在访问时,拉取到最新的数据。

服务端缓存

服务端缓存是整个缓存体系中的重头戏,从网站的架构演进中已经看到了服务端缓存是系统性能的重中之重了。

数据库是整个系统中的慢性子,有时候数据库调优能够以小搏大,在不改变架构和代码逻辑的前提下,缓存参数的调整往往是条捷径。

在系统开发的过程中,可以直接在平台侧使用缓存框架,当缓存框架无法满足系统对性能的要求时,就需要在应用层自主开发应用级缓存了,即使利用可供参考的开源架构,应用级缓存的开发也是一件有挑战的事情。

数据库缓存

数据库属于 IO 密集型的应用,主要负责数据的管理及存储。数据库缓存是一类特殊的缓存 , 是数据库自身的缓存机制。

大多数数据库不需要配置就可以快速运行,但并没有为特定的需求进行优化。在数据库调优的时候,缓存优化是一项很重要的工作。

以 MySQL 为例,MySQL 中使用了查询缓冲机制,将 SELECT 语句和查询结果存放在缓冲区中,以后对于同样的 SELECT 语句,将直接从缓冲区中读取结果,以节省查询时间,提高了 SQL 查询的效率。

Query cache 作用于整个 MySQL 实例,主要用于缓存 MySQL 中的 ResultSet,也就是一条 SQL 语句执行的结果集,所以仅仅只能针对 select 语句。

当打开了 Query Cache 功能,MySQL 在接受到一条 select 语句的请求后,如果该语句满足 Query Cache 的要求,MySQL 会直接根据预先设定好的 HASH 算法将接受到的 select 语句以字符串方式进行 hash,然后到 Query Cache 中直接查找是否已经缓存。

也就是说,如果已经结果在缓存中,该 select 请求就会直接将数据返回,从而省略了后面所有的步骤 (如 SQL 语句的解析,优化器优化以及向存储引擎请求数据等),从而极大地提高了性能。当然,当数据变化非常频繁的情况下,使用 Query Cache 可能会得不偿失。

当使用 InnoDB 存储引擎的时候,innodb_buffer_pool_size 参数可能是影响性能的最为关键的一个参数了,用来设置用于缓存 InnoDB 索引及数据块的内存区域大小,更像是 Oracle 数据库的 db_cache_size。

简单来说,当操作一个 InnoDB 表的时候,返回的所有数据或者查询过程中用到的任何一个索引块,都会在这个内存区域中去查询一遍。

另外,table_cache 是一个非常重要的 MySQL 性能参数,主要用于设置 table 高速缓存的数量。

由于每个客户端连接都会至少访问一个表,因此该参数与 max_connections 有关。当某一连接访问一个表时,MySQL 会检查当前已缓存表的数量。

如果该表已经在缓存中打开,则会直接访问缓存中的表已加快查询速度;如果该表未被缓存,则会将当前的表添加进缓存并进行查询。

在执行缓存操作之前,table_cache 用于限制缓存表的最大数目:如果当前已经缓存的表未达到 table_cache,则会将新表添加进来;若已经达到此值,MySQL 将根据缓存表的最后查询时间、查询率等规则释放之前的缓存。

当然,深入数据库还有很多值得学习的地方,需要专业的技能,这就是很多公司专门设有 DBA 角色的原因吧。

平台级缓存

在系统开发的时候,适当地使用平台级缓存,往往可以取到事半功倍的效果。 平台级缓存在这里指的是用来写带有缓存特性的应用框架,或者可用于缓存功能的专用库(如 PHP 中的 Smarty 模版库)。

在 Java 语言中,缓存框架更多,例如 EHcache,Cacheonix,Voldemort,JBoss Cache,OSCache 等等。

EHcache 是现在最流行的纯 Java 开源缓存框架,配置简单、结构清晰、功能强大,是从 hibernate 的缓存开始被广泛使用起来的。EHCache 又如下特点:

  • 轻量快速——EHcache 的线程机制是为大型高并发系统设计的;

  • 良性伸缩——数据可以伸缩到数 G 字节,节点可以到数百个;

  • 简洁灵活——运行时缓存配置,存活时间、空闲时间、内存和磁盘存放缓存的最大数目等是可以在运行时修改的;

  • 标准支持——Ehcache 提供了对 JSR107 JCACHE API 最完整的实现;

  • 强扩展性——节点发现,冗余器和监听器都可以插件化;

  • 数据持久——缓存的数据可以在机器重启后从磁盘上重新获得;

  • 缓存监听——提供了许多对缓存事件发生后的处理机制;

  • 分布式缓存——支持高性能的分布式缓存,兼具灵活性和扩展性。

EHcache 的系统结构如图所示:

另外,Voldemort 也是一款基于 Java 开发的分布式键-值缓存系统,像 JBoss 的缓存一样,Voldemort 同样支持多台服务器之间的缓存同步,以增强系统的可靠性和读取性能。

简单来说,就平台级缓存而言,只需要在框架侧配置一下属性即可,而不需要调用特定的方法或函数。

系统中引入缓存技术往往就是从平台级缓存开始的,平台级缓存也通常会作为一级缓存使用。

应用级缓存

当平台级缓存不能满足系统性能要求的时候,就要考虑使用应用级缓存了。应用级缓存,需要开发着通过代码来实现缓存机制。

这里是 NoSQL 的胜场,不论是 Redis 还是 MongoDB,以及 Memcached 都可以作为应用级缓存的重要技术。

一种典型的方式是每分钟或一段时间后统一生成某类页面存储在缓存中,或者可以在热数据变化时更新缓存。

面向 Redis 的分布式缓存

Redis 是一款开源的,基于 BSD 许可的,高级键值对缓存和存储系统,在应用级缓存中的作用举足轻重,例如,新浪微博有着几乎世界上最大的 Redis 集群。 

Redis 支持主从同步,数据可以从主服务器向任意数量的从服务器同步,从服务器可以是关联其他从服务器的主服务器。这使得 Redis 可执行单层树状复制。

由于完全实现了发布 / 订阅机制,使得从数据库在任何地方同步树的时侯,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。

支持 Redis 的客户端编程语言众多,可以满足绝大多数的应用,如图所示:

Redis 3.0 版本加入 cluster 功能,解决了 Redis 单点无法横向扩展的问题。Redis 集群采用无中心节点方式实现,无需 proxy 代理,客户端直接与 Redis 集群的每个节点连接,根据同样的哈希算法计算出 key 对应的 slot,然后直接在 slot 对应的 Redis 上执行命令。

在 Redis 看来,响应时间是最苛刻的条件,增加一层带来的开销是不能接受的。

因此,Redis 实现了客户端对节点的直接访问,为了去中心化,节点之间通过 gossip 协议交换互相的状态,以及探测新加入的节点信息。

Redis 集群支持动态加入节点,动态迁移 slot,以及自动故障转移。

基于 Redis 的多级缓存示例

一个使用了 Redis 集群和其他多种缓存技术的应用系统架构如图所示:

首先,用户的请求被负载均衡服务分发到 Nginx 上,此处常用的负载均衡算法是轮询或者一致性哈希,轮询可以使服务器的请求更加均衡,而一致性哈希可以提升 Nginx 应用的缓存命中率。

接着,Nginx 应用服务器读取本地缓存,实现本地缓存的方式可以是 Lua Shared Dict,或者面向磁盘或内存的 Nginx Proxy Cache,以及本地的 Redis 实现等,如果本地缓存命中则直接返回。

Nginx 应用服务器使用本地缓存可以提升整体的吞吐量,降低后端的压力,尤其应对热点数据的反复读取问题非常有效。

如果 Nginx 应用服务器的本地缓存没有命中,就会进一步读取相应的分布式缓存——Redis 分布式缓存的集群,可以考虑使用主从架构来提升性能和吞吐量,如果分布式缓存命中则直接返回相应数据,并回写到 Nginx 应用服务器的本地缓存中。

如果 Redis 分布式缓存也没有命中的时候,则会回源到 Tomcat 集群,在回源到 Tomcat 集群时也可以使用轮询和一致性哈希作为负载均衡算法。

当然,如果 Redis 分布式缓存没有命中的话,Nginx 应用服务器还可以再尝试一次读主 Redis 集群操作,目的是防止当从 Redis 集群有问题时可能发生的流量冲击。

在 Tomcat 集群应用中,首先读取本地平台级缓存,如果平台级缓存命中则直接返回数据,并会同步写到主 Redis 集群,然后再同步到从 Redis 集群。

此处可能存在多个 Tomcat 实例同时写主 Redis 集群的情况,可能会造成数据错乱,需要注意缓存的更新机制和原子化操作。

如果所有缓存都没有命中,系统就只能查询数据库或其他相关服务获取相关数据并返回,当然,我们已经知道数据库也是有缓存的。

整体来看,这是一个使用了多级缓存的系统。Nginx 应用服务器的本地缓存解决了热点数据的缓存问题,Redis 分布式缓存集群减少了访问回源率,Tomcat 应用集群使用的平台级缓存防止了相关缓存失效或崩溃之后的冲击,数据库缓存提升数据库查询时的效率。

正是多级缓存的使用,才能保障系统具备优良的性能。

基于云服务的分布式缓存

云服务不仅为软件系统的开发和部署带来了更多的敏捷性,而且提供了更多创新的可能性。当分布式缓存技术遇到云服务会是怎样的情形呢?EVCache 就是这样的一种技术。

EVCache 是一个开源、快速的分布式缓存,基于 Memcached 的内存存储 和 Spymemcached 客户端实现的解决方案,主要用在亚马逊弹性计算云服务 (AWS EC2)的基础设施上,为云计算做了优化,能够顺畅而高效地提供数据层服务。

EVCache 在 Netflix 内部是一个被广泛使用的数据缓存服务,所提供的低延迟且高可用的缓存方案可以很好地满足 Netflix 微服务架构需要,也用来做一般数据的存储。EVCache 能够使面向终端用户的应用,个性化算法和各种微服务都具备优良的性能。

EVCache 具有如下的特性:

  • 分布式的键值对存储 , 缓存可以跨越多个实例;

  • 数据可以跨越亚马逊云服务的可用区进行复制;

  • 通过 Netflix 内部的命名服务进行注册,自动发现新节点和服务;

  • 为了存储数据,键是非空字符串,值可以是非空的字节数组,基本类型,或者序列化对象,且小于 1 MB;

  • 作为通用的缓存集群被各种应用使用,支持可选的缓存名称,以命名空间避免主键冲突;

  • 一般的缓存命中率在 99% 以上;

  • 与 Netflix 驻留数据框架能够良好协作,典型的访问次序: 内存 ->EVCache -> Cassandra/SimpleDB/S3。

使用缓存技术所带来的最大影响可能是数据的不一致性。出于性能优先的考虑,具体的应用会依赖于 EVCache 来处理数据的不一致性。

对于存活时间很短的数据,用 TTL 设置数据的失效时间,对于长时间保留的数据,通过构建一致性检查来修复它们。

一个典型的用例是 Netflix 向用户推荐与已看历史中节目类似的电影或者电视节目,如下图所示:

内容相似性推荐服务给出了与已看历史中节目类似的电影或者电视节目的相似性列表。一旦计算出了相似性,就存储在 SimpleDB/S3 中,前端使用 EVCache。

当任何应用或者算法需要这些数据的时候,可以从 EVCache 提取数据,并返回结果。具体过程如下:

  1. 一个客户向 Web 应用发了一个页面请求,处理这一请求需要得到一个电影或电视节目的相似性列表;

  2. Web 应用查询 EVCache 来得到这些数据,这样场景的典型缓存命中率高于 99.9%;

  3. 如果缓存没有命中, Web 应用将调用相似性计算服务来计算这些数据;

  4. 如果已经计算过的数据也没有命中的话, 相似性计算服务将从 SimpleDB 中读取数据。如果在 SimpleDB 没有,相似性计算服务根据给出的电影或电视节目重新计算相似性;

  5. 相似性计算服务在计算出电影或电视节目的数据后,将数据写入到 EVCache 中;

  6. 最后,相似性计算服务生成客户端所需要的响应并返回给客户端。

EVCache 借助云服务的能力实现了高可用,高容错和全球部署等特性,为分布式缓存与云服务的融合提供了很有价值的参考。

结束语

总而言之,“缓存为王” 是因为在现代的软件系统中,缓存无处不在,是一种以空间换时间的艺术。尽管分布式缓存是一种非常复杂的技术,但是真正的这种技术是保证软件系统性能的关键手段。

近期热文

PHP 程序员危机

知名互联网公司校招 Java 开发岗面试知识点解析

从零开始,搭建 AI 音箱 Alexa 语音服务

修改订单金额!?0.01 元购买 iPhoneX?| Web谈逻辑漏洞

让你一场 Chat 学会 Git

接口测试工具 Postman 使用实践


「阅读原文」看交流实录,你想知道的都在这里

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值