今天,我们将深入探讨缓存的世界。缓存是构建可扩展、高性能系统的秘密武器。缓存有很多种类型,但在本文中,我们将重点介绍后端对象缓存(后端缓存)。掌握它将帮助您构建高性能且可靠的软件。
在本文中,我们将探讨:
什么是缓存?我们将探讨缓存,并解释它如何临时存储数据以实现更快的访问。
缓存的好处:了解缓存如何提高速度、减少服务器负载、改善用户体验甚至降低成本。
缓存模式:在本节中,我们将深入探讨使用缓存的不同方法。请记住,每种方法都有优点和缺点,因此请确保根据您的需求选择正确的模式!
缓存最佳实践:现在您知道如何存储和检索缓存数据。但是如何确保缓存数据保持最新状态?当缓存达到其容量时会发生什么?
何时不使用缓存:虽然缓存有很多好处,但有时最好避免使用。在错误的系统中实施缓存会增加复杂性,甚至可能降低性能。
创建高性能和可扩展的应用程序就是为了消除瓶颈并使系统更高效。数据库通常会因其存储和处理要求而成为系统性能的瓶颈。这使得它们成为昂贵的组件,因为它们需要经常扩展。
值得庆幸的是,有一个组件可以帮助减轻数据库资源的使用,同时提高数据检索速度——这个组件被称为缓存。
缓存是一种临时存储,旨在快速写入和读取数据。它使用低延迟内存存储和优化的数据结构来实现快速操作。您可能已经使用过 Redis 或 Memcached,或者至少听说过它们的名字。这是两个最流行的后端服务分布式缓存系统。Redis 甚至可以充当主数据库,但这是另一篇文章的主题!
缓存的主要优势在于速度。从缓存中读取数据比从数据库(如 SQL 或 Mongo)中检索数据要快得多。这种速度源于缓存使用字典(或 HashMap)数据结构进行快速操作,并将数据存储在高速内存中而不是磁盘上。
其次,缓存可减少数据库的负载。这样一来,应用程序就可以从缓存中获取所需的数据,而不必不断访问数据库。这大大降低了硬件资源的使用率;您的系统无需在磁盘上搜索数据,而是只需从快速内存中访问数据即可。
这些优势直接改善了用户体验,并可节省成本。您的应用程序响应速度更快,为用户带来更流畅、更令人满意的体验。
缓存可降低基础设施成本。虽然像 Redis 这样的分布式系统需要自己的资源,但总体节省的成本通常很可观。您的应用程序可以更高效地访问数据,从而有可能让您缩减数据库规模。但是,这需要权衡:如果您的缓存系统发生故障,请确保您的数据库已准备好处理增加的负载。
现在您已经了解了缓存的强大功能,让我们深入了解使用它的最佳方法!在本节中,我们将探讨两种基本模式类别:缓存写入模式和缓存未命中模式。这些模式提供了管理缓存更新和处理所需数据尚未在缓存中的情况的策略。
写入模式决定了应用程序如何与缓存和数据库交互。让我们来看看三种常见策略:回写、直写和绕写。每种策略都有独特的优势和权衡:
怎么运行的:
适用于:写入密集型应用程序,速度至关重要,为了提高性能可以接受一定的不一致性。示例包括指标和分析应用程序。
优点:
缺点:
怎么运行的:
优点:
缺点:
使用 Write-Around,您的应用程序可以将数据直接写入数据库,在写入过程中绕过缓存。为了填充缓存,它采用了一种称为缓存旁路模式的策略:
读请求到达:应用程序检查缓存。
缓存未命中:如果在缓存中找不到数据,应用程序将从数据库中获取数据,然后将其存储在缓存中以供将来使用。
优点:
缺点:
当您的应用程序所需的数据未在缓存中找到时,就会发生缓存未命中。以下是解决此问题的两种常见策略:
应用程序检查缓存。
当发生未命中时,它会从数据库获取数据,然后更新缓存。
重点:应用程序负责管理缓存。
使用 Cache-Aside 模式意味着您的应用程序将管理缓存。这种方法最常用,因为它很简单,不需要在应用程序以外的地方进行开发
应用程序发出请求,但不知道缓存。
一种专门的机制会检查缓存并在需要时从数据库获取数据。
缓存以透明方式更新。
读通模式降低了应用程序的复杂性,但增加了基础设施的复杂性。它有助于将应用程序资源转移给中间件。
总体而言,由于易于实现,使用带缓存的写回模式最为常用。不过,如果您有任何数据在缓存后会立即使用,我建议也采用写通模式。这将为读取性能带来些许好处。
在本节中,我们将探讨使用缓存的最佳做法。遵循这些做法将确保您的缓存保持最新数据并有效管理其存储。
假设您已将数据存储在缓存中,然后数据库进行了更新。这会导致缓存中的数据与数据库版本不同。我们将这种类型的缓存数据称为“过时数据”。如果没有缓存失效技术,您的缓存数据在数据库更新后可能会保持过时状态。要保持数据最新,您可以使用以下技术:
更新时缓存失效:更新数据库中的数据时,也更新相应的缓存条目。直写和回写模式本身可以处理此问题,但绕写/缓存旁写需要明确删除缓存数据。此策略可防止应用程序检索过时的数据。
生存时间 (TTL): TTL 是您在缓存中存储数据时可以设置的策略。使用 TTL,数据会在指定时间后自动删除。这有助于清除未使用的数据,并在发生失效时提供针对陈旧数据的故障保护。
如果您缓存了大量数据,缓存存储可能会填满。缓存系统通常使用内存,而内存通常比主数据库存储小。当缓存已满时,它需要删除一些数据以腾出空间。缓存替换策略决定要删除哪些数据:
最近最少使用 (LRU):此常见策略会逐出最长时间未使用(读取或写入)的数据。LRU 适用于大多数实际用例。
最不常用 (LFU):与 LRU 类似,但侧重于访问频率。新写入的数据可能会被逐出,因此请考虑添加一个预热期,在此期间不能删除数据。
其他替换策略如 FIFO(先进先出)、随机替换等也存在,但不太常见。
在深入研究缓存实现之前,重要的是要知道什么时候缓存可能不是最佳选择。缓存通常可以提高速度并减少数据库负载,但在以下情况下可能没有意义:
低流量:如果您的应用程序流量较低且响应时间仍然可以接受,那么您可能暂时不需要缓存。添加缓存会增加复杂性,因此最好在您面临性能瓶颈或预计流量会大幅增加时实施缓存。
您的系统写入量大:缓存在读取量大的应用程序中最有用。这意味着数据库中的数据很少更新,或者在更新之间多次读取。如果您的应用程序有大量写入,缓存可能会增加开销并降低速度。
在本文中,我们介绍了缓存的基础知识以及如何有效地使用它。以下是关键点的回顾:
确认需求:确保您的系统读取量大并且需要缓存提供的延迟减少功能。
明智地选择模式:选择与应用程序使用数据的方式相符的缓存写入和缓存未命中模式。
数据新鲜度:实施缓存失效策略,以防止提供过时的数据。
管理替换策略:选择缓存替换策略(如 LRU)来在缓存达到其容量时处理删除。