【后端面试基础】-【Redis篇】(六): Redis常见问题

89 阅读3分钟

这篇文章我们来介绍一些Redis中常见的问题以及它们的解决方案。

一、缓存雪崩

缓存雪崩指的是大量的不同key同一时间全部失效,所有请求都打到数据库中,导致数据库宕机。

解决方案:

  1. 在设置key的过期时间时加入随机数,使得key不在同一时间过期,给足系统同步缓存的时间。
  2. 使用分布式锁等锁机制,控制整个系统访问数据库的并发量。
  3. 热点数据设置不过期。

二、缓存击穿

缓存层被击穿,缓存中无访问的key,而数据库中有。这是缓存中key过期导致的。

解决方案:

  1. 基于分布式锁以及其他锁机制,控制访问数据库的并发量
  2. 热点key设置不过期。

三、缓存穿透

缓存层和数据库层都无访问的key,整个系统被穿透。

解决方案:

  1. 布隆过滤器,防止不存在的数据访问整个系统
  2. 缓存空值。

四、Redis中的大Key问题

在Redis中数据都是以k-v存储的,一般k只是起到索引标识的作用,所以不会很大,在Redis中的大Key一般指的是value过于庞大。

问题:

在前文中我们知道,Redis处理数据是单线程的,这样没有多线程的切换,让redis变得很快,但是如果k-v中的v过大,就会增加读取和处理的时间,从而阻塞整个线程,导致整个redis服务的访问性能下降。

解决方案:

对value进行拆分,把一个k-v合理的拆分成多个k-v存储。

五、缓存和数据库一致性问题

在高并发的系统中,由于存在着多线程操作,会导致缓存中的数据和数据库中的数据不一致。一般有三种方案来解决数据不一致的情况,缓存延迟双删、异步监听数据库binlog删除 + 重试、旁路缓存。 这里只介绍业务中经常使用的旁路缓存模式。

具体操作:

读操作:去缓存中读取数据,如果存在则返回;如果数据不存在,去数据库中读取数据,更新到缓存中,并返回。

写操作:更新数据库,删除缓存。

写操作更新和删除的顺序问题:

1.先删除缓存,再更新数据库,此时可能会出现如下操作。

当前数据情况:数据库 x =a , 缓存:x = a ; 线程1执行写操作第一步,先删除缓存。

当前数据情况:数据库 x =a , 缓存:空 ; 线程2执行读操作,此时缓存为空,读取数据库数据,更新缓存,并返回。

当前数据情况:数据库 x =a , 缓存:x = a ; 线程1执行写操作第二步,更新数据库 x = b。

当前数据情况:数据库 x =b , 缓存:x = a ; 线程1,2,3执行读操作,此时缓存与数据库数据已经不一致。

2.先更新数据库,再删除缓存,此时可能会出现如下操作。

当前数据情况:数据库 x =a , 缓存:x = 空 ; 线程1执行读操作,缓存不存在,去数据库中读取数据 x = a。

当前数据情况:数据库 x =a , 缓存:x = 空 ; 线程2执行写操作,更新数据库x = b , 并删除缓存。

当前数据情况:数据库 x =b, 缓存:x = 空 ; 线程1执行读操作第二步,更新缓存 x = a 。

当前数据情况:数据库 x =b , 缓存:x = a ; 线程1,2,3执行读操作,此时缓存与数据库数据已经不一致。

为什么采用方案2呢。因为操作数据库的时间比操作缓存的时间慢很多。当执行完数据库操作,再执行缓存操作,可粗略认为是同一时间,方案2的不一致基本不会出现。