系统设计之缓存(Caches)和内容分发网络(CDNs)设计
@TOC
推荐超级课程:
假设一家公司在芬兰的谷歌云数据中心的服务器上托管网站。对于欧洲用户,加载可能需要大约100毫秒,但对于墨西哥用户,加载可能需要3-5秒。幸运的是,有策略可以最大程度地减少远程用户的请求延迟。
缓存
缓存是一种用于提高系统性能和效率的技术。它涉及将某些数据的副本存储在临时存储区域(缓存)中,以便将来对该数据的请求可以更快地提供服务。
不同的缓存策略
缓存数据可以极大地提高应用程序的性能。通常有4个常见的地方可以存储缓存数据。
1. 浏览器缓存
浏览器缓存涉及将网站资源存储在用户的本地计算机上。当用户再次访问网站时,浏览器可以从本地缓存加载网站而不是再次从服务器获取所有内容。
禁用浏览器缓存:用户可以通过调整浏览器设置来禁用缓存。在大多数浏览器中,开发人员可以从他们的开发者工具中禁用缓存,通常可以在网络设置中找到。例如,您可以在Chrome的开发者工具的网络选项卡中使用“禁用缓存”选项。
存储位置:缓存存储在客户端硬盘上的目录中,由浏览器管理。浏览器缓存将HTML、CSS和JS捆绑文件存储在用户的本地计算机上,通常存储在浏览器管理的专用缓存目录中。
Cache-Control 头:Cache-Control: max-age=3600
指令告诉浏览器将文件缓存3600秒(1小时)。
缓存命中和缓存未命中
缓存命中 当请求数据已经存在于缓存中时发生。另一方面,** 缓存未命中** 当请求数据不在缓存中且需要从原始来源获取时发生。
您可以在浏览器的开发者工具中查看缓存是否命中或未命中,指示网络选项卡中的缓存状态。例如,响应头像 X-Cache: Hit
表示缓存命中。
2. 服务器缓存
服务器缓存涉及将经常访问的数据存储在服务器上,减少了对数据库查询等昂贵操作的需求。
位置:服务器端缓存存储在服务器本身或单独的缓存服务器上,可以存储在内存(如Redis)或磁盘上。
流程:通常,在查询数据库之前,服务器会检查缓存中的数据。如果数据在缓存中,则直接返回。
但如果数据不在缓存中,则服务器从数据库中检索数据,将其返回给用户,然后将其存储在缓存中以供将来的请求使用。
缓存失效
我们以上所述的过程是Write-Around 缓存,其中数据直接写入到永久存储中,绕过缓存。这是在写性能不那么关键的情况下使用的。
我们还有Write-Through 缓存。当数据同时写入到缓存和永久存储中时,这是Write-Through缓存。它确保数据一致性,但速度可能较慢。
另一种类型是Write-Back Cache。在这种情况下,数据首先写入缓存,然后在稍后写入永久存储。这提高了写性能,但在服务器或缓存服务器崩溃时存在数据丢失的风险。
选择取决于数据类型、访问模式和性能要求。
淘汰策略:缓存的决策制定者
淘汰策略做出关键决策,即当缓存装满时删除哪些项目。
让我们深入了解一些最常见的淘汰策略:
- 最近未使用(LRU): 想象一个队列,最后到达的最先离开。LRU就是遵循这个原则的。它跟踪使用历史并首先丢弃最近未访问的项目。这就像一个更偏爱新鲜体验的记忆。
- 先进先出(FIFO): FIFO是公平的典范——第一个进入缓存的项目是第一个离开的。这种方法不考虑数据的访问频率或最近性。它就像一个有礼貌的队列,每个人都得按顺序等待,不管重要性如何。
- 最不经常使用(LFU): LFU就像一个流行度竞赛。它跟踪每个项目的访问频率。那些被访问最少次数的项目首先被清除。这种策略偏向那些频繁被请求的项目。
自适应策略
一些系统实现自适应策略,结合这些基本策略的元素。这些更复杂的算法可以根据不断变化的数据访问模式调整其行为,确保在各种情况下实现最佳缓存性能。
自定义策略
在某些情况下,特别复杂的系统可能需要定制设计的淘汰策略。这些策略专门针对系统的独特需求进行调整,可以考虑各种因素,比如每个项目的大小、类型和检索成本。
淘汰策略的影响
淘汰策略的选择对缓存系统的性能有显著影响。选择良好的策略可以确保缓存仅存储最有效的数据,从而降低延迟,提高响应时间。
3. 数据库缓存
数据库缓存在缓存策略的领域中扮演着关键角色,对于增强对依赖数据库交互的应用程序的性能至关重要。
实现
数据库缓存可以通过两种主要方式实现:
- 内部缓存:这是数据库系统本身维护缓存。就像在数据库内置一个快速查找指南。
- 外部缓存:在这种方法中,外部缓存(如Redis或Memcached)与数据库一起工作。将其视为一个专门记住经常请求的数据的助手。
工作原理
当查询发送到系统时,数据库缓存像门卫一样介入。它首先检查自己的内存,看看是否已知这个查询的答案。如果结果在缓存中存在(缓存命中),则直接返回,从而避免数据库重新处理查询。
处理缓存未命中
缓存未命中就像遇到临时阻碍。当缓存没有所需数据时,系统会执行查询以对数据库执行操作。在检索所需信息之后,它不会止步于此 —— 它会将此结果存储在缓存中。这样,当下次相同的查询来拜访时,缓存已经准备好了答案。
理想的使用情况:数据库缓存的优势
数据库缓存特别适用于读取量大的应用程序 —— 那些某些查询就像不断播放的流行歌曲一样。在这些情况下,缓存显著减少了再次运行相同查询所需的时间,从而改善整体性能。
淘汰策略
与其他缓存系统一样,数据库缓存并非无穷无尽;它们也需要规则来决定什么留下什么删除。它们采用各种淘汰策略来有效管理内存使用。一个常见的策略是LRU(最近最少使用)。
性能影响
实施有效的数据库缓存策略可显著改善应用程序的响应速度和效率。它减少了数据库的负载,加快了数据检索速度,并确保用户体验更加流畅。但是,像任何有用的工具一样,它需要谨慎调整和管理。缓存方法的选择、缓存大小和淘汰策略必须根据应用程序的具体需求进行校准,以实现最佳性能。
内容分发网络(CDN)
CDN是分布在地理位置的服务器网络,通常用于提供静态内容,如JavaScript、HTML、CSS、图像和视频资源。它们会从原始服务器缓存内容并从最近的CDN服务器向用户提供。
CDN 工作原理
内容分发网络(CDN)的过程如下:
- 初始请求:用户请求一个文件 —— 也许是图像、视频或网页。
- 最近服务器响应:此请求迅速重定向到最接近的CDN服务器。
- 内容传输:如果这个服务器已经缓存了内容,则直接将其交付给用户。
- 拉取和转发:在CDN服务器没有这个内容的情况下,它会从源服务器检索内容,存储(缓存)它,然后发送给用户。这一步确保下次有人请求相同内容时,可以立即得到。
CDN 类型:推送 vs 拉取
基于拉取的CDN:在这里,CDN起到了主动作用。它在第一次用户请求时从源服务器拉取内容,非常适合经常更新静态内容的站点。
基于推送的CDN:在这种情况下,您掌握着主动权。您直接将内容上传到CDN。这种方法非常适合大文件,这些文件不经常更改,但需要在发生更改时进行快速分发。这就像将包裹送到快递公司进行交付。
控制 CDN 行为
我们使用请求头来控制CDN 的行为。
- Cache-Control: 这个头部是规定 CDN 和浏览器缓存存储内容的规则书,包含指令如
max-age
、no-cache
、public
和private
。 - Expires: 这是内容的到期日期,标志着内容何时过期。
- Vary: 这个头部根据特定的请求头适应提供内容,确保交付正确版本的内容。
选择 CDN 和原始服务器
选择 CDN 时:
- 您正在分发静态资产(图像、CSS、JavaScript)。
- 高可用性和性能在各个地区至关重要。
- 卸载原始服务器是重点。
什么时候直接到原始服务器:
- 内容是动态的,经常更改或个性化的。
- 需要实时处理或新鲜数据。
- 涉及复杂的服务器端逻辑,CDN 无法处理。
结语
总之,缓存和 CDN 在提升网站性能、减少延迟以及确保互联网上内容传递的可扩展性和有效性方面至关重要。它们在任何高流量、性能关键型的 Web 应用程序的架构中都是基础。
CDN 好吃
- 降低延迟: 通过从距用户更近的地点提供内容,CDN显著降低延迟。
- 高可用性和可扩展性: CDN能够处理高流量,并且对硬件故障具有弹性。
- 提升安全性: 许多CDN提供安全功能,如DDoS防护和流量加密。
缓存好处
- 降低延迟: 由于数据是从附近缓存中获取,而不是远程服务器,因此数据检索速度更快。
- 减轻服务器负荷: 缓存减少对主要数据源的请求次数,降低服务器负荷。
- 提升用户体验: 更快的加载时间带来更好的用户体验。