分布式基础概念-分布式缓存[1]

2023-11-17 17:15:34 浏览数 (1)

如何避免缓存穿透、缓存击穿、缓存雪崩?

缓存雪崩是指缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。

缓存雪崩解决方案:

  • 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
  • 给每一个缓存数据增加相应的缓存标记,记录缓存是否失效,如果缓存标记失效,则更新数据缓存。
  • 缓存预热
  • 互斥锁

缓存穿透是指缓存和数据库中都没有的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉。

缓存穿透解决方案:

  • 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
  • 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击
  • 采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力

缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。和缓存雪崩不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。

缓存击穿解决方案

  • 设置热点数据永远不过期。
  • 加互斥锁

分布式系统中常用的缓存方案有哪些?

  • 客户端缓存:页面和浏览器缓存,APP缓存,H5缓存,localStorage和sessionStorage
  • CDN缓存:内容存储:数据的缓存,内容分发:负载均衡
  • nginx缓存:静态资源
  • 服务端缓存:本地缓存,外部缓存
  • 数据库缓存:持久层缓存(mybatis,hibernate多级缓存),mysql查询缓存
  • 操作系统缓存:Page Cache、Buffer Cache

如何保证数据库与缓存的一致性?

由于缓存和数据库是分开的,无法做到原子性的同时进行数据修改,可能出现缓存更新失败,或者数据库更新失败的情况,这时候会出现数据不一致,影响前端业务

  • 先更新数据库,再更新缓存。缓存可能更新失败,读到老数据
  • 先删缓存,再更新数据库。并发时,读操作可能还是会将旧数据读回缓存
  • 先更新数据库,再删缓存。也存在缓存删除失败的可能最经典的缓存 数据库读写的模式,CacheAsidePattern。

读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。 更新的时候,先更新数据库,然后再删除缓存。

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

  • 删除更加轻量,延迟加载的一种实现,更新可能涉及多个表、比较耗时
  • 延时双删:先删除缓存,再更新数据库,休眠1s、再次删除缓存。写数据的休眠时间则在读数据业务逻辑的耗时基础上,加几百ms即可。这么做的目的,就是确保读请求结束,写请求可以删除读请求造成的缓存脏数据,并发还是可能读到旧值覆盖缓存终极方案:将访问操作串行化
  1. 先删缓存,将更新数据库的操作放进有序队列中
  2. 从缓存查不到的查询操作,都进入有序队列

会面临的问题:

  1. 读请求积压,大量超时,导致数据库的压力:限流、熔断
  2. 如何避免大量请求积压:将队列水平拆分,提高并行度。
  3. 保证相同请求路由正确。

缓存过期都有哪些策略?

  • 定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量
  • 惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,但是很消耗内存、许多的过期数据都还存在内存中。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。
  • 定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key(是随机的),并清除其中已过期的key。该策略是定时过期和惰性过期的折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。
  • 分桶策略:定期过期的优化,将过期时间点相近的key放在一起,按时间扫描分桶。

常见的缓存淘汰算法

  • FIFO(First In First Out,先进先出),根据缓存被存储的时间,离当前最远的数据优先被淘汰;
  • LRU(Least Recently Used,最近最少使用),根据最近被使用的时间,离当前最远的数据优先被淘汰
  • LFU(Least Frequently Used,最不经常使用),在一段时间内,缓存数据被使用次数最少的会被淘汰。

布隆过滤器原理,优缺点

位图:int10,每个int类型的整数是4*8=32个bit,则int10一共有320 bit,每个bit非0即1,初始化时都是0

  • 添加数据时,将数据进行hash得到hash值,对应到bit位,将该bit改为1,hash函数可以定义多个,则一个数据添加会将多个(hash函数个数)bit改为1,多个hash函数的目的是减少hash碰撞的概率
  • 查询数据:hash函数计算得到hash值,对应到bit中,如果有一个为0,则说明数据不在bit中,如果都为1,则该数据可能在bit中优点:
  • 占用内存小
  • 增加和查询元素的时间复杂度为:O(K), (K为哈希函数的个数,一般比较小),与数据量大小无关
  • 哈希函数相互之间没有关系,方便硬件并行运算
  • 布隆过滤器不需要存储元素本身,在某些对保密要求比较严格的场合有很大优势
  • 数据量很大时,布隆过滤器可以表示全集
  • 使用同一组散列函数的布隆过滤器可以进行交、并、差运算缺点:
  • 误判率,即存在假阳性(False Position),不能准确判断元素是否在集合中
  • 不能获取元素本身
  • 一般情况下不能从布隆过滤器中删除元素

友情链接:关于Redis作为缓存的三大问题以及缓存一致性为题可参考文章

对线面试官-Redis(缓存的三大问题) 对线面试官-Redis(作为缓存的一致性问题)

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

0 人点赞