Redis复习:高可用与缓存之道

Redis复习:高可用与缓存之道

2025年7月16日 Redis 高可用 缓存 分布式

一、 Redis高可用:保障服务不中断

单机的Redis实例虽然性能卓越,但一旦宕机,整个服务将不可用。为了解决这个问题,Redis提供了多种高可用方案,其中最基础和常用的是主从复制,而**哨兵(Sentinel)**则在此基础上实现了自动故障转移。

1. 主从复制 (Master-Slave Replication)

主从复制是Redis高可用的基石。它允许你将一个Redis服务器(主节点,Master)的数据复制到其他Redis服务器(从节点,Slave)。

  • 工作原理
    • 全量同步:当从节点第一次连接主节点,或者断线重连后无法进行增量同步时,会进行全量同步。主节点会生成RDB文件发送给从节点,从节点加载RDB文件恢复数据。
    • 增量同步:全量同步完成后,主节点会将后续的所有写命令发送给从节点,从节点执行这些命令来保持数据同步。
  • 优点
    • 读写分离:主节点负责写操作,从节点负责读操作,分担了主节点的压力,提高了并发量。
    • 数据冗余:多个从节点存储相同的数据副本,提高了数据安全性。
    • 故障恢复基础:当主节点宕机时,可以手动将一个从节点提升为新的主节点。
  • 缺点
    • 无法自动故障转移:主节点宕机后,需要人工干预才能恢复服务,存在服务中断时间。
    • 写操作瓶颈:所有写操作都集中在主节点,无法水平扩展写能力。
2. 哨兵 (Sentinel):自动故障转移的守护者

哨兵模式是Redis官方推荐的高可用解决方案。它由一个或多个哨兵实例组成,这些哨兵实例监控Redis主从节点,并在主节点发生故障时自动进行故障转移。

  • 工作原理
    • 监控:哨兵会持续监控主节点和从节点的运行状态。
    • 通知:当被监控的某个Redis实例出现问题时,哨兵会向其他哨兵和客户端发送通知。
    • 自动故障转移:如果主节点宕机,多个哨兵会通过投票机制选举出一个领导者哨兵,由它负责从现有的从节点中选择一个最优的从节点,将其提升为新的主节点,并通知其他从节点复制新的主节点,同时更新客户端的连接信息。
  • 优点
    • 自动故障转移:无需人工干预,大大缩短了服务中断时间。
    • 高可用性:即使部分哨兵实例宕机,只要多数哨兵正常运行,系统依然可以进行故障转移。
  • 缺点
    • 部署复杂:需要部署至少三个哨兵实例,增加了部署和维护的复杂性。
    • 写操作瓶颈依然存在:哨兵模式解决了主节点故障问题,但写操作依然集中在单点。

二、 缓存的"坑"与应对之道

缓存是提升系统性能的利器,但使用不当也会带来一系列问题。以下是缓存领域最常见的三大问题及其解决方案。

1. 缓存穿透 (Cache Penetration)

定义:查询一个根本不存在的数据,导致请求直接打到数据库,并且数据库也查不到,每次都穿透缓存,给数据库带来巨大压力。

  • 场景:恶意攻击者频繁查询不存在的key,或者业务逻辑中存在大量对不存在数据的查询。
  • 解决方案
    • 缓存空对象:如果数据库查询结果为空,也把这个空结果缓存起来,并设置一个较短的过期时间。下次再查询这个key时,直接从缓存返回空,避免了对数据库的访问。缺点是会占用额外的缓存空间。
    • 布隆过滤器 (Bloom Filter):在查询数据库之前,先通过布隆过滤器判断key是否存在。如果布隆过滤器判断key不存在,则直接返回,避免访问数据库。布隆过滤器有误判率(即可能将不存在的key误判为存在),但不会将存在的key误判为不存在。
2. 缓存击穿 (Cache Breakdown)

定义:某个热点key在缓存中过期了,此时有大量并发请求同时访问这个key,这些请求会同时打到数据库,导致数据库压力骤增甚至宕机。

  • 场景:某个商品秒杀活动开始前,商品详情页的缓存突然过期,大量用户同时涌入。
  • 解决方案
    • 互斥锁 (Mutex Lock):当缓存失效时,只有第一个请求能够获取到锁并去数据库加载数据,其他请求则等待。加载完成后,释放锁,其他等待的请求从缓存中获取数据。这可以有效防止大量请求同时打到数据库。
    • 设置永不过期:对于一些绝对的热点数据,可以考虑将其设置为永不过期,或者在后台定时刷新缓存,避免其过期。
    • 逻辑过期:缓存中不设置物理过期时间,而是设置一个逻辑过期时间字段。当查询发现逻辑过期时,异步地去更新缓存,同时返回旧数据。
3. 缓存雪崩 (Cache Avalanche)

定义:在某一时间段内,缓存中大量key同时失效,导致所有请求都涌向数据库,数据库瞬间压力过大而崩溃。

  • 场景:缓存系统宕机,或者大量缓存设置了相同的过期时间,在某个时间点集中失效。
  • 解决方案
    • 设置随机过期时间:在设置缓存的过期时间时,在原有过期时间的基础上增加一个随机值,使缓存的过期时间分散开来,避免集中失效。
    • 多级缓存:引入多级缓存,例如本地缓存+Redis缓存,当Redis缓存失效时,请求可以先尝试从本地缓存获取数据。
    • 熔断与限流:当数据库压力过大时,可以采取熔断机制,暂时停止对数据库的访问,或者进行限流,只允许部分请求通过,保护数据库。
    • 服务降级:在系统压力过大时,关闭部分非核心功能,保证核心功能的可用性。