美文网首页
如何保证双写一致性

如何保证双写一致性

作者: lubberland66 | 来源:发表于2020-04-02 16:43 被阅读0次

    Cache Aside Pattern

    1、读的时候,先读缓存,缓存没有的话,就读数据库,取出数据后放入缓存,同时返回响应。

    2、更新的时候,先删除缓存,然后更新数据库

    3、缓存设置ttl

    问题一:为什么第二步不是更新缓存,而是删除缓存

     数据库更新后,缓存数据的更新操作不是必须的。有可能频繁的更新了缓存,但在此期间并没有读操作,所以使用lazy的思想,可以把缓存更新放在读操作流程里。

    问题二:第二步为什么先删除缓存,见下图

    主要是考虑操作失败的情况:

    1、如果采用先更新库再删除缓存的方式,如果删除缓存失败,则缓存里是脏数据

    2、如果采用先删除缓存再更新库的方式,无论是哪种操作失败,都不会有脏数据

    选择先删除缓存,然后更新数据库的方式,读取和更新并发执行仍有可能不一致  见下图

    上图的步骤执行完,缓存里是旧数据。虽然几率很小,不过仍然有可能发生。

    简单版解决方法:

       更新操作优化为:先删除缓存,再更新数据库,1秒后,再删除缓存。这样就把有可能造成的脏缓存删除掉

        优点:实现简单

        缺点:1秒内有可能有脏缓存,虽然几率很小

    问题:延时删除操作失败,仍然是脏缓存数据。

    解决方案?

        将删除失败的key放入消息队列,业务从消息队列消费,重试删除key的操作,直到删除成功。

    复杂版解决方案:

        把读操作和更新操作串行化操作。

        一、程序实现

            根据操作数据的唯一表示,把对数据的操作路由到某一个程序的内部队列里。

            1、读操作时,如果缓存没有读到数据,则将“读取数据库,更新缓存”的操作放到内部队列里

            2、更新操作,直接放到内部队列里

            优点:不需要借助第三方消息队列

            缺点:负载均衡处需要把数据的读操作和更新操作做路由处理

    二、消息队列实现

        将“程序实现”步骤中的内部队列替换成消息队列(rabbitmq、kafka等)

        优点:保证一致性,不需要路由

        缺点:流程比较长,处理时间较长

    参考:

    https://blog.csdn.net/suifeng629/article/details/93903185

    https://www.cnblogs.com/rjzheng/p/9041659.html

    相关文章

      网友评论

          本文标题:如何保证双写一致性

          本文链接:https://www.haomeiwen.com/subject/beyxphtx.html