1. 引言

在本篇文章中,我们将探讨缓存中常见的写操作实现方式。我们会分析每种策略的优缺点,并讨论在实际应用中如何选择合适的写策略。

不过在深入之前,我们先来回顾一下缓存的基本概念,确保大家对缓存的作用和相关术语有统一的理解。

2. 缓存基础

缓存是一种用于提供对底层存储快速访问的中间层组件。通常来说,缓存的存储介质更快但也更昂贵,因此容量有限。在某些场景下,缓存可能是我们系统的一部分,而原始数据存储(backing store)则可能由外部系统管理。

缓存的核心目标是提升操作的延迟(latency)和吞吐量(throughput)

缓存命中(cache hit)是指请求的数据在缓存中存在;反之则称为缓存未命中(cache miss)。

缓存中的数据可能会因为以下原因被移除(eviction):

  • 数据未被使用
  • 数据体积过大
  • 系统认为继续保留不划算

这与缓存失效(invalidation)不同。缓存失效是指我们主动将缓存标记为无效,可能是直接删除缓存条目,或者在下次请求时重新从原始存储加载数据。

3. 写策略概述

缓存的写策略(write policy)决定了在执行写操作时缓存的行为方式。写策略直接影响缓存的一致性、性能和可靠性等关键特性。

常见的写策略包括:

  • Write-through(直写)
  • Write-around(绕写)
  • Write-back(回写)

接下来我们逐一介绍这些策略。

4. Write-through(直写)

如果你的应用优先考虑数据一致性,通常会选择 Write-through 策略。在这种模式下,写操作会同步更新缓存和底层存储,只有当两者都成功时,才向客户端返回响应。

如果当前写入的数据不在缓存中,我们会先将它加载到缓存中再执行写操作:

Cache Cache WT

优点

  • 数据一致性高
  • 实现简单

缺点

  • 写操作延迟较高(需要等待底层存储完成)

5. Write-around(绕写)

Write-through 策略的一个问题是:如果写入的数据短期内不会被读取,那么就会“污染”缓存,造成缓存空间浪费。

为了避免这种缓存污染(cache pollution),我们可以采用 Write-around 策略。它在缓存未命中时不将数据写入缓存,而是直接写到底层存储

Cache Cache WT NA

此外,还有一种变种叫做 Write-invalidate,它在缓存命中时写入底层存储的同时,将缓存中的条目标记为无效

优点

  • 避免缓存污染
  • 适合写多读少的场景

缺点

  • 缓存命中率可能降低
  • 可能导致后续读操作延迟增加

6. Write-back(回写)

Write-back 是三种策略中性能最好的一种。它先将数据写入缓存并立即返回响应,然后在后台异步地将数据刷新到底层存储。

这种异步刷新可以有多种触发方式:

  • 在写入响应前触发
  • 定期触发
  • 基于缓存条目的“脏状态”(dirty state)触发

在 CPU 缓存中,我们使用“脏位”(dirty bit)来标识缓存是否被修改。在软件缓存中,通常更倾向于在写入响应前触发异步刷新。

Cache Cache WB

优点

  • 写操作延迟低
  • 支持批量写入,提升吞吐量

缺点

  • 存在一致性风险
  • 缓存数据丢失可能导致数据丢失(如断电)

⚠️ 踩坑提示:Write-back 策略下,如果系统崩溃或断电,未刷新到底层存储的“脏”数据将丢失。因此,必须配合持久化机制或冗余设计使用。

此外,如果存在多个缓存实例或绕过缓存的写操作,可能出现数据顺序混乱的问题。为了解决这个问题,我们需要实现所谓的 事务序列化(transaction serialization),以保证操作顺序的一致性。

这类问题和解决机制统称为 缓存一致性(cache coherence)

7. 写分配策略(Write Allocation)

前面我们提到,在 Write-through 策略中,即使缓存未命中,也可以选择是否将数据写入缓存。这个选择被称为“写分配(write allocation)”。

写分配策略主要有两种:

  • Write allocate(写分配):在写入前将数据加载到缓存中
  • No-write allocate(不写分配):绕过缓存,直接写入底层存储

在 Write-back 策略中,一般推荐使用 Write allocate,因为它可以利用缓存的优势进行异步刷新。而 No-write allocate 更适合 Write-through 场景,尤其是写多读少的场景。

8. 权衡与选择

在选择缓存写策略时,我们需要综合考虑以下几个因素:

策略 一致性 性能 数据安全性 适用场景
Write-through 对一致性要求高
Write-around 写多读少,避免缓存污染
Write-back ✅✅ 对性能要求高,能容忍短暂不一致

此外,还要考虑:

  • 数据访问模式(读多写少 / 写多读少)
  • 数据局部性(是否频繁访问)
  • 是否有多个缓存实例或并发写入路径

9. 总结

本文我们详细介绍了三种常见的缓存写策略:Write-through、Write-around 和 Write-back。

每种策略都有其适用场景和潜在风险。没有一种写策略是万能的,选择时应根据以下因素综合判断:

  • 系统对数据一致性的要求
  • 对性能(延迟/吞吐)的关注程度
  • 数据访问模式
  • 系统架构是否支持并发写入或多缓存实例
  • 是否具备数据持久化或冗余机制

最终建议

  • 如果你追求强一致性,用 Write-through;
  • 如果你追求写性能,用 Write-back,但要做好数据持久化和缓存一致性保障;
  • 如果写操作不频繁被读取,考虑 Write-around 来避免缓存污染。

原始标题:Cache Write Policy

« 上一篇: 里氏替换原则
» 下一篇: 大数据 vs 数据挖掘