高并发系统设计十一-缓存的使用一(如何选择缓存的读写策略)

缓存的使用一-如何选择缓存的读写策略

缓存在实际项目中的使用,选择缓存策略时需要考虑不同的因素:

  • 缓存中是否有可能被写入脏数据
  • 策略的读写性能如何
  • 是否存在缓存命中率下降的情况

1、Cache Aside(旁路缓存)策略

更新数据时不更新缓存,而是删除缓存中的数据,在读取数据时,发现缓存中没有了数据之后,再从数据库中读取数据,更新到缓存中。

这个策略是以数据中的数据为准,缓存中的数据是按需加载的,可以分为读策略和写策略:

  • 读策略的步骤
    • 从缓存中读取数据
    • 如果缓存命中,则直接返回数据
    • 如果缓存中不命中,则从数据库中查询数据
    • 查询到数据后,将数据写入到缓存中,并返回给用户
  • 写策略
    • 更新数据库中的记录
    • 删除缓存记录

1.1、场景分析

1、在写策略中是否可以先删除缓存,后更新数据呢?这样是不行的,这样可能会出现缓存数据不一致的问题:

假设某个用户的年龄为20,请求A更改用户年龄为21,所有它会删除缓存中的内容,这个时候,请求B要读这个用户的年龄,它查询缓存发现未命中后,会从数据库中读取到年龄为20,并写入到缓存中,但是请求A继续更改数据库,将用户的年龄更新为了21,就造成了缓存和数据库的不一致性。

2、新注册一个用户,是否也要按照这个策略来处理呢?

当新注册一个用户,按照这个更新策略,写数据库,然后清理缓存(这时候缓存中也么有数据可清理)。可当我注册用户后立即读取用户信息,并且数据库主从分离时,会出现因为主从延时而读不到用户信息的情况。

解决这个问题,在插入新数据到数据库之后,直接写入缓存中,这样后续的读请求就会从缓存中读取数据了,并且因为是新注册的用户,所有不会存在并发更新用户信息的情况。

1.2、Cache Aside 存在的问题

就是写入比较频繁,缓存中的数据会被频繁地清理,对缓存的命中率有一些影响。

如果业务对缓存的命中率有要求的话,可以考虑两种解决办法:

  • 在更新数据时也更新缓存,只是在更新缓存前先加一个分布式锁,在同一时间只允许一个线程更新缓存,就不会产生并发问题了,但是这样的话会对写入性能有一定的影响
  • 更新数据库时也更新缓存,只是给缓存加一个较短的过期时间,这样即使缓存出现缓存不一致的情况,缓存的数据也会很快的过期,对业务影响也是比较小的

2、Read/Write Through(读穿 / 写穿)策略

用户只与缓存打交道,由缓存和数据库通信,写入或者读取数据。这就好比你在汇报工作的时候只对你的直接上级汇报,再由你的直接上级汇报给他的上级,你是不能越级汇报的。

2.1、Write Through 的策略

先查询要写入的数据在缓存中是否已经存在,如果已经存在,则更新缓存中的数据,并且由缓存组件同步更新到数据库中,如果缓存中数据不存在,我们把这种情况叫做“Write Miss(写失效)”,然后 使用“No-write allocate(不按写分配)”,做法是不写入缓存中,而是直接更新到数据库中

一般来说,我们可以选择两种“Write Miss”方式:一个是“Write Allocate(按写分配)”,做法是写入缓存相应位置,再由缓存组件同步更新到数据库中;另一个是“No-write allocate(不按写分配)”,做法是不写入缓存中,而是直接更新到数据库中。

2.2、Read Through 策略

先查询缓存中数据是否存在,如果存在则直接返回,如果不存在,则由缓存组件负责从数据库中同步加载数据

这种策略方式使用较少

  • Memcached、Redis 都不提供写入数据库
  • Write Through 策略中写数据库是同步的,这个对性能会有较大的影响。

3、Write Back(写回)策略

写入数据时只写入缓存,并且把缓存块儿标记为“脏”的。而脏块儿只有被再次使用时才会将其中的数据写入到后端存储中

发布了57 篇原创文章 · 获赞 3 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/wmdkanh/article/details/105568828