• 缓存与数据库一致性原则


    https://blog.csdn.net/striveb/article/details/95110502

    一、场景:

      两个用户发起下单请求,下单前需要查库存是否有剩余。

      用户甲 :1、阶段1 :访问缓存库存,获取到缓存库存数量为1;

          2、阶段1 :缓存数量为1,即有库存,准备更新,然后删除缓存库存;

          3、阶段3 :然后更新数据库库存为 0;

      用户乙:1、阶段2 :访问缓存库存,发现库存为空;

          2、阶段2:然后再去访问数据库(此时用户甲,还没有修改数据库,此时数据库库存数量为1),发现数据库存为1,然后写入缓存库存改为1 。 

      

    原因:  

      产生以上问题的原因是阶段2的时间长,延迟了用户甲在第三步的无法及时更新数据的库存数量的操作。

      阶段2,这段时间那么长,有以下原因。

      1、JVM垃圾收集的时候,会产生停止线程的场景。GC 产生 stop world

      2、操作系统的时候,有上下文切换,耗时较长;

      3、应用程序同步磁盘的时候,如果操作过程有是同步 io, 要等操作完成之后才能更新数据库;

      4、内存的 free 空间已经很小, 这时候会 swap 到持久化层面,这时候访问操作很久;

      5、操作更新数据库,由于网络的问题,包丢了;

      6、在操作的时候,有人在运维,就可以挂起虚拟机;

    二、常见缓存访问模式

    1、本地缓存(Cache-Aside)

      缓存不直接与数据库交互

      应用 服务1 访问数据库获取数据,再把数据存到本地缓存。

      

    2、 缓存中间件(Cache-Aside)

       左边全链路,右边统一数据访问服务

      左边全链路的延迟更少,减少中间缓件。

      右边的应用服务逻辑更简单,对用户更友好。

      

    2.1、第一种

      全链路

    2.1.1、读取缓存

      先访问缓存,查找数据;如果缓存返回失败,直接查找数据库,并放入缓存;

     2.1.2、更新操作

      1、先更新缓存,再更新数据库(更新不删除缓存)。

      如果更新数据库不成功,导致缓存和数据库不一致。

      如下问题

       

       用户 B :1、阶段1:查找缓存,发现没有

            2、阶段1到3:查找数据库

            3、阶段3: 更新数据库

      用户 A:1、阶段1到2:更新缓存;

          2、阶段3:更新缓存成功,再更新数据库

      A 更新的数据被B 更新的覆盖

     2、先更新数据库,再更新缓存(更新不删除缓存) 

       也会出现问题,也会产生数据不一致。

     3、先删除缓存,再更新数据库(更新删除缓存), 

       没有数据不一致的问题,但也有问题。

     4、先更新数据库,再删除缓存(更新删除缓存)

       也有问题。 

    2.2、第二种

      通过 统一数据访问服务,来决定先访问 数据库 还是 缓存,应用服务不直接访问数据库和缓存。

      应用服务通过 get 和 set 访问,具体的由 统一数据访问服务决定。

      

    2.3、缓存和数据库交互 Through

    2.3.1、read Through

        

      1、应用服务先访问缓存,找需要的数据;

      2、如果没有相关数据,则缓存向数据库查找请求

      3、数据库返回数据给缓存

      4、数据写入缓存,并返回给应用服务

     2.3.2、write through

      

      1、第一步查找更新缓存是否在缓存中

      2、如果在缓存中,则直接更新缓存中的数据

      3、如果没有查找到缓存中的数据,则直接更新数据库

        第二部中的数据更新完缓存中的数据,同步也会写回到数据库

         

    2.3.3、write behind

      

    三、一致性更新目标

      过期时间 TTL 

      1、最终一致性:过期了回取数据库最新值

      2、剔除冷的缓存,节省缓存空间,提升效率

    3.1、异步更新(最终一致性)

        

    3.2、重试机制(最终一致性)

      

      1、数据访问服务先更新数据库

      2、再删除缓存,如果删除缓存失败

      3、失败的记录放入消息队列

      4、消费消息队列的消息(即使删除失败的记录)

      5、重试删除操作

    3.3、强一致性

        

       将更新数据库和更新缓存当作事务依据 ACID 的原则。

      

  • 相关阅读:
    Linux机器学习软件配置
    安装linux14.04
    Navicat无法连接SqlServer数据库
    linux命令行安装teamviewer
    Ubuntu14.04+Dell 7060安装无线/有线网络驱动
    启动一个SpringBoot的maven项目
    HTML5新增特性
    HTML 表格|表单
    HTML 基础
    初识 wijmo-grid
  • 原文地址:https://www.cnblogs.com/Jomini/p/13968603.html
Copyright © 2020-2023  润新知