0%

缓存读写一致性

缓存读写一致性问题

在知乎看(搜索)到这么一个问题:如何用redis/memcache做Mysql缓存层?刚好最近学的项目只是用到了mysql,这里学习整理一下缓存的知识。PS:强烈建议学习陈皓大神的文章以及阅读英文原文,中文博客知识需要进行筛选。

知乎问题https://www.zhihu.com/question/27738066

陈皓(左耳朵耗子)的文章https://coolshell.cn/articles/17416.html

首先要讨论的是,缓存删除还是更新的问题。什么情况下选择删除,什么情况下选择更新

  • 缓存存储的value是序列化的对象

    序列化和反序列化需要消耗cpu的资源,删除缓存成本更低,等出现下次数据汇源时再更新。

  • 高并发的场景

    两个并发操作,一个查询缓存,一个更新操作。先更新(选择删除缓存),再查询,此时无法命中缓存,会先把老的数据从数据库读出放入缓存中,然后更新数据库。此时缓存中是脏的数据,并且一直这样脏下去。所以,这种场景应该选择缓存更新,而不是删除Cache后再从数据库更新。

更新缓存的四种模式

Cache Aside Pattern

缓存预留模式,最常用的模式之一。这种模式的重点在于先把数据更新到数据库,成功后让缓存失效,最后更新缓存。

在并发的情况下,更新前查询缓存命中,此时是老数据,更新过程中查询只有两种情况:1)更新过程中命中缓存,获取脏数据,之后再查询都是新的数据;2)更新后让缓存失效,此时查询无法命中缓存,直接从数据库获取新的数据。

这样不会出现上面谈到的缓存中总是脏数据的逻辑问题。但是也不代表这种做法是稳定安全的。如果在读数据的过程没有命中缓存,同时有一个并发写的操作,读操作从数据库得到脏数据,数据库更新,之前的读操作再把老的数据放进去,就会造成脏数据。

总结:Facebook采用这种做法,是选择将脏数据概率降至最低,而不是选择成本较高的2PC和Paxos分布式一致性协议保证数据的一致性。

Read/Write Through Pattern

Read/Write through模式(直写模式)是把更新数据库的操作,交给缓存,认为后端是一个单一的存储,这个存储维护自己的Cache,对应用层很友好。

缺点:相比write back模式,数据修改时同时写入数据库,写入速度慢。

  • Read Through

    在查询/读操作中更新缓存,缓存失效时服务自己从数据库中加载。

  • Write Through

    和Read Through相仿,区别在于是在更新/写数据时发生。当有数据更新的时候,如果没有命中缓存,直接更新数据库,然后返回。如果命中了缓存,则更新缓存,然后再由Cache自己更新数据库(这是一个同步操作)。

Write Behind Caching Pattern

也称作write back回写模式。在数据更新时只写入缓存Cache。只有数据被替换出缓存时,被修改的缓存数据才会写到后端存储。

优点:写入速度快,不需要同步写到数据库中;异步操作也可以合并对同一个数据的多次操作,提高性能。

缺点:一旦更新后的数据未被写入存储时,出现系统断电的现象,数据无法找回。

write back流程图:

图片说明