浅析缓存的读写策略

x33g5p2x  于2022-07-22 转载在 其他  
字(1.6k)|赞(0)|评价(0)|浏览(310)

前言

提起缓存,我们首先想到缓存是一种存储数据的组件,它的作用是让对数据的请求能更快地返回。

我们一般会把不经常改变而且又需要快速访问的数据进行缓存,常用的做法是将这些数据写进内存中,当需要访问的时候能快速地返回需要的结果。

实际上,凡是速度相差较大的两种硬件之间,用于协调两者数据传输差异的结构,都可以称为缓存。

在日常开发过程中,我们就经常将数据放在的本地缓存(escache)或者外部缓存(Redis)中。

缓存的读写策略

缓存听起来很简单,无非就是优先读缓存,缓存不命中就从数据库中查询,查询到了再写回缓存。但实际上,根据不同业务场景,缓存的读写策略也是不同。我们就以最常见的缓存+数据库的场景来分析。

Cache Aside(旁路缓存)策略

Cache Aside是我们使用最多的策略,缓存不和数据库直接进行交互,而是由应用程序来同时和缓存以及数据库打交道。Cache Aside的名字正体现了这个模式,Cache在应用的一旁(aside)。

读数据时
  1. 程序需要判断缓存中是否已经存在数据
  2. 当缓存中已经存在数据(也就是缓存命中,cache hit),则直接从缓存中返回数据
  3. 当缓存中不存在数据(也就是缓存未命中,cache miss),则先从数据库里读取数据,并且存入缓存,然后返回数据
写数据时
  1. 先更新数据库
  2. 再删除缓存中对应的数据

Read-Write Through (读写穿透)策略

Read/Write Through Pattern中服务端把缓存视为主要数据存储,从中读取数据并将数据写入其中。缓存服务负责将此数据读取和写入 DB,从而减轻了应用程序的职责。

读数据时 (Read Through)
  1. 从缓存中读取数据,读取到就直接返回 。
  2. 读取不到的话,则由缓存组件先从数据库加载,写入到缓存后返回响应。

写数据时 (Write Through)
  1. 先查缓存,缓存中不存在,直接更新数据库。
  2. 缓存命中,则先更新缓存,然后缓存服务自己更新数据库(同步更新缓存和数据库)

在 Cache Aside下,发生读请求的时候,如果 cache 中不存在对应的数据,是由客户端自己负责把数据写入 cache,而 Read-Through策略则是缓存服务自己来写入缓存的,这对客户端是透明的。

Read/Write Through策略的特点是由缓存节点而非用户来和数据库打交道,在我们开发过程中,这种策略比较少使用,原因在于我们一般使用的缓存组件(Redis或者Memcached)都不提供写入数据库的功能。只有本地缓存Guava Cache中的Loading Cache有Read Through策略的影子。

可以看出,由于Write Through写数据时需要同时更新数据库,对于性能会有比较大的影响。那么我们可不可以异步更新数据库呢?这就是接下来的Write Back策略。

Write-Back(异步缓存写入)策略

Write-Back策略和Read-Write Through策略的共同点在于两者都是由缓存服务来负责缓存和数据库的读写。

不同点在于Write-Back将缓存作为可靠的数据源,每次都只写入缓存,而写入数据库则采用异步的方式,比如当数据要被移除出缓存的时候再存储到数据库或者一段时间之后批量更新数据库。

优点:在于读写速度非常快,因为都是从缓存中直接读取和写入。对于服务中数据库不可用有一定的容忍度,当数据库不可用时,也能正常处理结果,待数据库恢复后再重新更新数据。同时也降低了数据库压力,写数据库操作可以放在业务流量较低的时候进行。

缺点:有数据丢失的风险,如果缓存服务挂掉而数据没有及时写入数据库中,则数据会丢失。

适合场景: 数据经常变化又对数据一致性要求没那么高的场景,比如浏览量、点赞量

总结

这三种缓存读写策略各有优劣,需要我们根据具体的业务场景选择更适合的。如果读多写少,且对于数据一致性要求高,可以使用Cache Aside策略。如果写多读少,且对于数据一致性要求不高,可以Read-Write Through或者Write-Back策略。

Ryan.ou

相关文章