zoukankan      html  css  js  c++  java
  • 缓存与数据库的数据一致性的解决方案

    使用redis作为mysql缓存数据库流程:

    先读缓存数据,缓存数据有,则立即返回结果;如果没有数据,则从数据库读数据,并且把读到的数据同步到缓存里,提供下次读请求返回数据。

    虽说这样能减轻数据库压力,但是如果修改删除数据,在多线程高并发的场景下会有可能导致缓存和数据库数据不一致问题,那该如何解决呢?

    场景一:

    问题的根源其实是读数据与写数据请求同时并发时,数据库与缓存数据已更新,但访问的数据还是老数据,出现了脏读数据,我们假设读请求流程没有问题,那就分析写请求流程的优化

    1. 先更新缓存,再更新数据库

    这个方案肯定不行。原因是更新缓存成功,更新数据库出现异常了,导致缓存数据与数据库数据完全不一致。

    1. 先更新数据库,再更新缓存

    这个方案同样不行,原理跟第一个一样,数据库更新成功了,缓存更新失败,同样会出现数据不一致问题。

    解决

    我们遇到写请求时,可用先删除缓存数据,再更新数据库,这样不管数据库更新失败还是缓存删除失败,缓存与数据库始终一致。这种方案一般可满足上万人并发操作了,因为删除缓存到更新数据库的时间可以用毫秒计算,正常的并发影响不大。

    场景二:

    上亿级并发访问,导致缓存与数据不一致。

    解决

    方案一:读写分离

    读请求只访问缓存,写请求只修改数据库和缓存

    写请求修改数据库和缓存是事务性动作,如果更新数据库成功,更新缓存失败,则回滚数据库,保证缓存与数据库数据强一致。这样实现了读写分离,不仅提高了读的响应速度,由写请求负责缓存与数据库一致,只有写请求成功才会影响到缓存的内容,时效性大大增强。

    方案二:队列存储请求

    沿用场景一的解决方案,为解决其缺陷,添加队列,凡是遇到写请求,则将写请求放入队列中,由队列对写请求统一管理,写请求处理成功,则从队列中删除。当有一个读请求过来时,到队列查询,是否有对应的写请求,如果有则放入队列中,等待写请求执行完之后再执行读请求。为防止某个请求阻塞情况,为其设置超时机制或者过期机制。

    场景三:

    访问量大,处理器来不及处理,队列内的请求数量越来越高,则会影响查询效率。

    解决:

    分布式数据库集群,再加上消息队列(kafka等)

  • 相关阅读:
    Spring Boot 2 (四):使用 Docker 部署 Spring Boot
    Spring Boot 2 (三):Spring Boot 2 相关开源软件
    ConnectionString属性(网速慢的情况下研究Connect Timeout)
    Flexbox布局入门笔记
    ASP.Net一般处理程序Session用法
    AngularJS 插值字符串 $interpolate
    浅谈AngularJS的$parse服务
    VsCode 解决vim插件,不能使用ctrl+c的问题(目标卸载im)
    win10远程桌面 CredSSP加密Oracle修正的解决办法
    fatal:'origin' does not appear to be a git repository fatal:Could not read from remote repository
  • 原文地址:https://www.cnblogs.com/vinic-xxm/p/11911691.html
Copyright © 2011-2022 走看看