zoukankan      html  css  js  c++  java
  • redis缓存与数据库一致性

    Cache Aside Pattern

    (1)读的时候,先读缓存,缓存没有的话,那么就读数据库,然后取出数据后放入缓存,同时返回响应

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

    先删除后更新

    避免更新过程中新来的读请求读到旧缓存数据。或者修改了数据库后删除缓存操作失败了,就会导致redis与数据库不一致的问题。

    为什么不是更新而是删除?

    • 避免不必要的计算
    • lazy懒加载思想,很多资源查询率并没有那么高,等到用时再去查就可以。

    超高并发场景

    如果亿级流量超高并发访问,cache aside pattern会出现删除缓存成功,但是更新数据库还没完成时新的读请求就来了,此时读库拿到应该要更新的旧数据又缓存起来,造成数据不一致的问题。

    可以设计一个队列让读写操作串行。

    1. 更新操作先删除缓存,然后放入队列等执行成功后出队
    2. 访问请求来到时发现缓存为空并且队尾有排队的更新操作,那么他就需要排队,等更新操作完成后再访问,完成后出队
    3. 访问请求来到时发现缓存为空并且队尾有排队的访问请求,不排队但是需要等待队列为空后再访问缓存

    该解决方案要注意读请求长时阻塞

    由于读请求进行了非常轻度的异步化,所以一定要注意读超时的问题,每个读请求必须在超时时间范围内返回

    该解决方案,最大的风险点在于说,可能数据更新很频繁,导致队列中积压了大量更新操作在里面,然后读请求会发生大量的超时

    务必通过一些模拟真实的测试,看看更新数据的频繁是怎样的

    另外一点,因为一个队列中,可能会积压针对多个数据项的更新操作,因此需要根据自己的业务情况进行测试,可能需要部署多个服务,每个服务分摊一些数据的更新操作

    如果一个内存队列里居然会挤压100个商品的库存修改操作,每隔库存修改操作要耗费10ms区完成,那么最后一个商品的读请求,可能等待10 * 100 = 1000ms = 1s后,才能得到数据

    这个时候就导致读请求的长时阻塞

    一定要做根据实际业务系统的运行情况,去进行一些压力测试,和模拟线上环境,去看看最繁忙的时候,内存队列可能会挤压多少更新操作,可能会导致最后一个更新操作对应的读请求,会hang多少时间,如果读请求在200ms返回,如果你计算过后,哪怕是最繁忙的时候,积压10个更新操作,最多等待200ms,那还可以的

    如果一个内存队列可能积压的更新操作特别多,那么你就要加机器,让每个机器上部署的服务实例处理更少的数据,那么每个内存队列中积压的更新操作就会越少

  • 相关阅读:
    Ansible template中j2文件调用var中定义变量报错解决办法
    Ansible 获取hosts中的分组ip
    VUE UI网站汇总
    vue rules详解与实例
    Python 获取设备ip地址
    Flask && Vue 虚拟机申请平台(从开发到部署)
    Vue 把获取到的可编辑表格的值传给后端
    SQLAlchemy基本使用,创建表,增删改查
    Ansible 角色(roles)一键部署redis集群(三主三从)
    Flask 数据库相关操作
  • 原文地址:https://www.cnblogs.com/ren-kai/p/12811622.html
Copyright © 2011-2022 走看看