zoukankan      html  css  js  c++  java
  • 缓存一致性问题

    缓存更新策略

    被动更新: 设置key过期的时间,让其自动失效。
    主动更新: 更新DB的时候,同时更新缓存
    一般业务都是主动更新和被动更新结合使用。
    

    缓存更新实现

    1. 调用者调用。失败重试3次,再失败,扔给消息队列异步处理。消息队列从数据库取最新的更新,保证成功
    2. DB中间件监听DB变化,更新缓存
    利用DB中间件监听DB变化(比如阿里的Canal中间件,点评的Puma),从而对缓存进行更新。
    这种办法的一个好处就是:把缓存的更新逻辑,和业务逻辑解藕。业务只更新DB,缓存的更新被放在另外一个专门的系统里面
    
    主动更新 问题
    存在一个问题:你是先更新缓存,后更新DB;还是反过来?
    下面分别分析以下2个场景,假设有2个线程,t1, t2:
    (1) 先更新缓存,后更新DB。假设有如下的执行系列:
    
    t1更新缓存;
    t2读缓存,因为t1把缓存更新了,导致t2没读到。从db中读,然后更新缓存;
    t1更新DB上述操作系列会导致缓存脏数据。 
    但是这个不更新 缓存再读都是错的。只有等到下次更新才行。
    但是更新操作总是比读操作少
    
    (2)先更新DB,后更新缓存。假设有如下操作序列:
    
    t1更新DBt2更新DBt2更新缓存;
    t1更新缓存。
    
    • 1 上述操作系列会导致缓存脏数据。 但是这个不更新 缓存再读都是错的。只有等到下次更新才行。 但是更新操作总是比读操作少

    • 2 这个出现的情况概率小点。同时更新可以加乐观锁 再加上缓存过期失效策略,只会有部分时间不一致

    • 一句话,无论谁先谁后,只要更新缓存和更新DB不是原子的,就可能导致不一致。只是从实际业务来讲,一般缓存也都是保持“最终一致性“,而不是和DB的强一致性。

    • 并且一般建议先更新DB,再更新缓存,优先保证DB数据正确。

    强一致

    锁/分布式锁
    

    缓存穿透

    某个key,先查cache没查到,再查db也没有查到。 这种key的存在,会导致cache一直没办法命中,压力一直打在db上面。如果访问很高频,可能会压垮DB。

    解决

    - 当查询DB没查到时,往缓存中写入一个空值(缺省值),这样第2次再查,就不会打到DB上了。
    
    

    缓存雪崩

    缓存机器挂了,保证缓存的可用性 解决

    • 应用内也保持应用内缓存
    • 提高缓存的HA。比如缓存的主从复制。
    • 对DB的访问实行限流、降级

    缓存并发

    缓存过期后将尝试从后端数据库获取数据,这是一个看似合理的流程。但是,在高并发场景下,有可能多个请求并发的去从数据库获取数据, 对后端数据库造成极大的冲击,甚至导致 “雪崩”现象。此外,当某个缓存key在被更新时,同时也可能被大量请求在获取,

    • 解决 :锁/分布式锁 重试解决
    类似“锁”的机制,在缓存更新或者过期的情况下,
    先尝试获取到锁,当更新或者从数据库获取完成后再释放锁,其他的请求只需要牺牲一定的等待时间,即可直接从缓存中继续获取数据。
    

    其他方法 不建议

    由于数据库层面的读写并发,引发的数据库与缓存数据不一致的问题(本质是后发生的读请求先返回了),可能通过两个小的改动解决:
    1)修改服务Service连接池,id取模选取服务连接,能够保证同一个数据的读写都落在同一个后端服务上
    2)修改数据库DB连接池,id取模选取DB连接,能够保证同一个数据的读写在数据库层面是串行的
  • 相关阅读:
    GameBuilder见缝插针游戏开发系列(AA)
    Ant—使用Ant构建一个简单的Java工程(两)
    linux下一个C语言要求CPU采用
    Chart.js报告
    HDU5187 zhx's contest(计数问题)
    hdoj 5087 Revenge of LIS II 【第二长单调递增子】
    poj 2503 Babelfish
    python发送电子邮件
    [Angular2 Router] Using snapshot in Router
    [Angular2 Form] Use RxJS Streams with Angular 2 Forms
  • 原文地址:https://www.cnblogs.com/clds/p/9122930.html
Copyright © 2011-2022 走看看