• 高并发架构基石【一】——缓存概述


    类型

    本地缓存

    在进程的内存中缓存,是内存访问,没有远程交互开销,性能最好,但受限于单机容量,一般缓存较小且无法扩展。

    分布式缓存

    可以很好解决本地缓存的问题,一般分布式缓存都具有良好的水平扩展能力,对较大数据量的场景也能应对自如,但需要进行远程请求,性能不如本地缓存。

    多级缓存

    多级缓存用于平衡本地缓存和分布式缓存,实际业务中也一般采用多级缓存,访问频率最高的部分热点数据采用本地缓存,其他热点数据放在分布式缓存中。

    淘汰策略

    FIFO (Fist in first out) 

    淘汰最早的数据。先进先出, 如果一个数据最先进入缓存中,则应该最早淘汰掉。

    LRU (Least recently used) 

    剔除最近最少使用的数据。最近最少使用,如果数据最近被访问过,那么将来被访问的几率也更高。

    LFU (Least frequently used)

    剔除最近使用频率最低的数据。最不经常使用,如果一个数据在最近一段时间内使用次数很少,那么在将来一段时间内被使用的可能性也很小。

    缓存问题

    缓存更新方式

    第一个问题是缓存更新方式,这是决定在使用缓存时就该考虑的问题。

    缓存的数据在数据源发生变更时需要对缓存进行更新,数据源可能是 DB,也可能是远程服务。更新的方式可以是主动更新。数据源是 DB 时,可以在更新完 DB 后就直接更新缓存。

    当数据源不是 DB 而是其他远程服务,可能无法及时主动感知数据变更,这种情况下一般会选择对缓存数据设置失效期,也就是数据不一致的最大容忍时间。

    这种场景下,可以选择失效更新,key 不存在或失效时先请求数据源获取最新数据,然后再次缓存,并更新失效期。

    但这样做有个问题,如果依赖的远程服务在更新时出现异常,则会导致数据不可用。改进的办法是异步更新,就是当失效时先不清除数据,继续使用旧的数据,然后由异步线程去执行更新任务。这样就避免了失效瞬间的空窗期。另外还有一种纯异步更新方式,定时对数据进行分批更新。实际使用时可以根据业务场景选择更新方式。

    缓存不一致

    第二个问题是数据不一致的问题,可以说只要使用缓存,就要考虑如何面对这个问题。缓存不一致产生的原因一般是主动更新失败,例如更新 DB 后,更新 Redis 因为网络原因请求超时;或者是异步更新失败导致。

    解决的办法是,如果服务对耗时不是特别敏感可以增加重试;如果服务对耗时敏感可以通过异步补偿任务来处理失败的更新,或者短期的数据不一致不会影响业务,那么只要下次更新时可以成功,能保证最终一致性就可以。

    缓存穿透

    产生原因

    原因可能是外部的恶意攻击,例如,对用户信息进行了缓存,但恶意攻击者使用不存在的用户id频繁请求接口,导致查询缓存不命中,然后穿透 DB 查询依然不命中。这时会有大量请求穿透缓存访问到 DB。

    解决方案

    1.对不存在的用户,在缓存中保存一个空对象进行标记,防止相同 ID 再次访问 DB。不过有时这个方法并不能很好解决问题,可能导致缓存中存储大量无用数据。

    2.使用 BloomFilter 过滤器,BloomFilter 的特点是存在性检测,如果 BloomFilter 中不存在,那么数据一定不存在;如果 BloomFilter 中存在,实际数据也有可能会不存在。非常适合解决这类的问题。

    缓存击穿

    概念

    就是某个热点数据失效时,大量针对这个数据的请求会穿透到数据源。

    解决方案

    1.可以使用互斥锁更新,保证同一个进程中针对同一个数据不会并发请求到 DB,减小 DB 压力。

    2.使用随机退避方式,失效时随机 sleep 一个很短的时间,再次查询,如果失败再执行更新。

    3.针对多个热点 key 同时失效的问题,可以在缓存时使用固定时间加上一个小的随机数,避免大量热点 key 同一时刻失效。

    缓存雪崩

    产生原因

    产生的原因是缓存挂掉,这时所有的请求都会穿透到 DB。

    解决方案

    1.使用快速失败的熔断策略,减少 DB 瞬间压力;

    2.使用主从模式和集群模式来尽量保证缓存服务的高可用。

    实际场景中,这两种方法会结合使用。

  • 相关阅读:
    JavaScript深入浅出补充——(一)数据类型,表达式和运算符
    Linux简介,虚拟机安装,网络设置,桌面和vim安装
    JavaScript对象之document对象
    python之MySQL学习——数据查询
    python框架Scrapy中crawlSpider的使用
    在Scrapy中使用IP池或用户代理更新版(python3)
    封装IP池和用户代理相应的类(python3)
    在Scrapy中使用IP池或用户代理(python3)
    scrapy工程创建及pycharm运行
    python框架Scrapy报错TypeError: 'float' object is not iterable解决
  • 原文地址:https://www.cnblogs.com/yadongliang/p/12494635.html
Copyright © 2020-2023  润新知