缓存写入策略

当系统将数据写入缓存时,缓存还必须在某一时刻将这些数据写入后端存储设备。缓存将数据写入后端存储设备的时机是由缓存写入策略所控制的。

缓存具有两种基本的写入方式:

  • 直写式(Write Through):将数据同步写入缓存和后端存储设备。
  • 回写式(Write Back)(也叫做后写式):首先,将数据写入缓存。然后,缓存会延缓将这些数据写入至后端存储设备,直到缓存块包含的数据即将被新的数据修改/替换。

回写式缓存是更加难以实现的,因为它需要跟踪必须覆盖的缓存位置,并且将它们标记为脏块,稍后才能将其中的数据写入至后端存储设备。只有当回收脏块的缓存空间时,脏块中的数据才会回写至后端存储设备,这种行为被称为懒写入。因为这个原因,所以回写式缓存的每次读取未命中(Read Miss)(此时会将某个缓存块替换为另一个缓存块)经常需要访问两次内存才能满足要求:第一次,将被替换的数据从缓存回写至存储设备;第二次,获取需要的数据。

其他策略也有可能触发数据回写。客户端可能会大量修改缓存中的数据,然后会显式地通知缓存将数据回写至后端存储设备。

写入操作不会返回任何数据,因此有两种方式可以应对写入未命中(Write Miss)的情况:

  • 写分配(Write Allocate):也叫做写时获取(Fetch On Write)。这种方式会将发生写入未命中的地址中的数据加载至缓存,然后执行写入命中(Write Hit)操作。通过这种方式,写入未命中就会类似于读取未命中。
  • 无写分配(No Write Allocate):也叫做写不分配(Write No Allocate)写附近(Write Around)。这种方式不会将发生写入未命中的地址中的数据加载至缓存,而是直接将这些数据写入至后端存储设备。通过这种方式,只有读取操作才会被缓存。

直写式策略和回写式策略都可以使用上述两种写入未命中策略,但是它们通常可以成对使用,如下所示:

  • 回写式缓存会使用写分配策略,期望对相同的位置进行后续的写入操作(或读取操作),此时的数据已经缓存。读取和写入的流程,如下图所示:
    回写式缓存的写分配策略

  • 直写式缓存会使用无写分配策略。此处,后续的写入操作不会有任何性能改善,因为它们仍然需要将数据直接写入至后端存储设备。读取和写入的流程,如下图所示:
    直写式缓存的无写分配策略

除了缓存之外的其他实体也有可能会修改后端存储设备中的数据,这就导致缓存中的数据拷贝可能会过期或者陈旧。或者,当客户端更新缓存中的数据时,这些数据在其他缓存中的拷贝,也会变得陈旧。缓存管理器之间的通信协议能够保证多个缓存之间的数据一致性,这种协议称为缓存一致性协议