Redis缓存技术常见问题

Redis缓存技术常见问题

 次点击
11 分钟阅读

Redis缓存技术常见问题

2025-7-25

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如字符串(strings), 散列(hashes), 列表(lists),集合(sets),有序集合(sorted sets) 与范围查询,bitmaps,hyperloglogs 和 地理空间(geospatial) 索引半径查询。Redis 内置了复制(replication),LUA脚本(Lua scripting),LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的磁盘持久化(persistence), 并通过Redis哨兵(Sentinel)和自动分区(Cluster)提供高可用性(high availability)

为了缓解数据库的压力,避免应用直接访问数据库,会在应用层与数据库之间添加一个缓存层提高系统性能,加快数据访问速度,这个缓存层通常会使用redis

引入了缓存层,就会有缓存异常的三个问题,分别是缓存雪崩、缓存击穿、缓存穿透。此外,还有缓存同步的问题,在文章末尾介绍。

这里我们主要以redis为例


1. 缓存穿透

缓存穿透 是指请求的数据在redis中没有对应的数据(缓存),从而导致直接向数据库中请求,这种请求一旦过多,会导致数据负载过高,影响系统可用性。这种大量请求穿过缓存直接请求数据库的现象就叫缓存穿透

常见的解决方案有两种:

1. 缓存空数据

如果Redis查不到数据,数据库也查不到,就把这个Key存进Redis,值设为空,下次再查询时就不需要再查询数据库。

优点:实现简单,维护方便

缺点:额外的内存消耗,在数据库进行添加操作时可能造成数据短期的不一致

可以对null的key设置较短的ttl(失效时间),及时释放内存

在数据进行添加操作时及时更新缓存中的数据

2.布隆过滤

通过特殊的布隆算法对数据进行统计,布隆过滤器的作用是判断一个key是否存在,若返不存在则一定不存在,若存在则大概率存在(存在一定的误判率)。在缓存之前再加一层布隆过滤器,在查询的时候先去布隆过滤器查询 key 是否存在,如果不存在就直接返回。

优点:内存占用相对较少

缺点:实现较复杂,存在误判

3.增加索引的复杂度,避免恶意请求空id

设置一定id格式,对请求进行格式过滤,避免非法请求


2. 缓存雪崩

缓存雪崩 是指在同一时段出现大规模的缓存失效或redis服务宕机,导致大量的请求直接访问数据库,给数据库带来巨大压力

解决方案:

1.给不同的key的TTL添加随机值

避免大量的key在同时间失效

2.提高redis服务的可靠性

搭建redis集群等

3.熔断机制

当流量到达一定的阈值时,直接返回系统拥堵拒绝服务,防止过多地请求数据库。保证部分用户可以正常使用,其他用户等待服务恢复。

4.提高数据库的容灾能力

可以采取分库分表,读写分离等策略

5.利用多级缓存

除redis缓存等,还可以有一定的nginx缓存,jvm缓存等补救方案


3. 缓存击穿

缓存击穿 又可以称为热点key问题 ,即一个被高并发访问并且缓存重建业务较复杂 的key突然失效,导致这段时间内的数据请求直接访问数据库,从而带来巨大压力。

解决方案:

1. 逻辑过期(保证了可用性)

业务允许的话,对于热点的key可以设置永不过期的key,或者逻辑过期的key,逻辑过期是指并不直接设置TTL,而是为这个key多维护一个字段,称为过期时间,在使用时确保不会过期,等到不需要使用时检查逻辑过期时间手动进行删除,这个删除过程需要加锁,未拿到锁的线程直接返回旧数据。

优点:线程无需等待,性能较好

缺点:不保证一致性,有额外内存消耗,实现复杂

2.互斥锁(保证了一致性)

使用互斥锁。如果缓存失效的情况,只有拿到锁才可以查询数据库,降低了在同一时刻对数据库的请求。redis提供了一个setnx的方法,当一个key不存在时才能对其赋值,可以使用这个方法实现互斥。

优点:无额外内存消耗,保证一致性,实现简单

缺点:线程需要等待,影响性能,可能有死锁风险


4. 缓存同步问题

redis缓存有三种更新策略,分别是内存淘汰过期淘汰主动更新

高一致性需求情况下一般使用主动更新为主,过期淘汰为辅的策略

主动更新是由调用者实现的,常见的主动更新实现方法有三种

  1. Cache Aside:在更新数据库的同时完成对缓存的更新,通常采用先更新数据库再删除缓存再同步的方法,而不是先删除缓存再同步

  2. Read/Write Through:将redis与数据库集成为一个服务,保证操作一致性,对外开放接口,调用者无需关心一致性问题。这个方法实现较复杂且没有较为成熟的方案。

  3. Write Back:调用者的数据操作直接针对缓存操作,再由独立线程实现对缓存的数据同步到数据库,不过当缓存不稳定时,容易造成数据不一致。

这些主动更新方案中常用的是第一种,采用事务机制实现原子性操作,这里选择删除缓存而不是直接更新缓存的原因是因为直接更新缓存会带来很多无效的操作,以及线程安全问题


双写一致性

双写一致性问题是指在分布式系统中,同时操作数据库(如MySQL)和缓存(如Redis)时,因网络故障、系统崩溃或并发高,导致缓存中的数据与数据库中的实际数据不一致的情况。

1. 延迟双删

  • 在更新数据库后,暂停一段时间再次删除缓存,以清理并发产生的脏数据。

2. 分布式锁

  • 使用分布式锁或乐观锁来控制并发访问,并保证每次只有一个请求能够操作缓存和数据库

3. 异步通知(使用MQ)

  • 先删除缓存再更新数据库,然后使用异步线程或消息队列来重建缓存。

© 本文著作权归作者所有,未经许可不得转载使用。