缓存旁路是最常见的缓存策略之一。当缓存命中(cache hit)时,数据访问延迟主要由通信延迟决定,通常较小,因为缓存可以部署在靠近应用程序的缓存服务器上,甚至直接在应用程序的内存中。
但在缓存未命中时,缓存是被动存储,由应用程序负责更新缓存。即缓存仅报告未命中,应用程序需要从底层存储中获取数据并更新缓存。
工作流程
如图 1 所示,应用程序通过缓存键(cache key)从缓存中查找值。缓存键决定了应用程序需要的数据。
如果键存在于缓存中,缓存返回与该键关联的值,应用程序直接使用。
如果键不存在或已过期(缓存未命中),应用程序需要处理这种情况。应用程序从底层存储(通常是数据库)查询数据,并将结果存储到缓存中。
例如,假设你正在缓存用户信息,并使用用户 ID 作为查找键。在缓存未命中的情况下,应用程序通过用户 ID 从数据库查询用户信息,将查询结果转换为适合缓存的格式(例如 JSON),然后以用户 ID 为键、用户信息为值更新缓存。
优点
缓存旁路之所以流行,是因为它易于实现。开发者可以轻松设置一个缓存服务器(如 Redis),用于缓存数据库查询或服务响应。缓存服务器是被动的,不需要了解底层数据库的细节或数据的映射方式,所有缓存管理和数据转换都由应用程序完成。
在许多场景中,缓存旁路是降低应用延迟的简单有效方法。通过将最相关的数据存储在靠近应用程序的缓存服务器中,可以隐藏数据库访问的延迟。
缺点
数据一致性问题:如果有多个并发读者同时查找同一键,应用程序需要协调并发缓存未命中的处理,否则可能导致多次数据库访问和缓存更新,进而造成后续缓存查询返回不一致的值。
事务支持缺失:由于缓存和数据库互不了解,应用程序需要负责协调数据更新,因此无法提供事务支持。
尾部延迟(tail latency):缓存未命中时,访问延迟取决于数据库的读取延迟。虽然缓存命中时访问很快,但未命中的情况会导致显著的延迟,因此数据库的地理位置延迟仍然很重要。