Redis
一、Redis三大件 1.1 缓存穿透 在用户访问数据的时候,这个数据既不在缓存也不再数据库,就会导致这个请求哪里都没打中,直接穿透了这两层数据库,当有大量这样的数据到达的时候就会导致数据库压力增大。 布隆过滤器:利用一个位数组和多个哈希函数,快速判断一个元素是绝对不存在还是可能存在于数据库中。 接口层参数校验:最基本的防线,在网关或API入口处,对请求参数进行合法性检查,例如检查ID的格式、范围、类型是否符合预期。 黑名单:对于已知的恶意用户ID、IP或异常key,可以将其维护在一个Redis Set或独立的黑名单列表中。 缓存空值:当数据库查询结果为空时,程序不直接返回,而是向Redis中写入一个特殊标记的值(如空字符串""或"NULL"),并为其设置一个较短的过期时间(TTL),例如30秒到5分钟。 互斥锁:当缓存未命中时,不是所有请求都一窝蜂去查数据库,而是通过分布式锁(基于Redis SETNX实现)来控制,只允许一个请求去数据库查询并回填缓存,其他请求则短暂等待后重试读取缓存。必须设置锁超时:防止拿到锁的请求崩溃,导致锁永不释放,形成死锁。等待策略:未抢到锁的请求重试次数或等待时间需要设上限,避免线程长时间阻塞。 限流与熔断降级:在系统层面配置限流规则(如基于 QPS),当针对某些key的请求速率超过阈值时,直接快速失败或返回降级内容,避免数据库承受超出其承载能力的流量。对于确认无法处理的异常来源,可以触发熔断,暂时切断对特定接口或IP的访问。 1.2 缓存击穿 在用户访问数据的时候,这个数据的hot key过期了,就会有大量请求大道数据库,击穿了redis这一层缓存,导致数据库压力增大 互斥锁:同上,只允许一个请求去数据库重建缓存,其他请求等待片刻后重新读取缓存 逻辑过期:就是让hot key在物理上永不过期,用户可能会短暂读到旧数据,因此该方案要求业务场景能容忍最终一致性,例如商品详情页、首页 Banner、排行榜等。 大数据预热:对于可预知的热点(如大促商品),通过定时任务在缓存逻辑过期或物理过期前主动刷新,使其“永不失效”。这通常与逻辑过期策略配合使用,形成“异步刷新 + 定时保底”的双重保障。 熔断降级和互斥锁结合:当系统检测到数据库压力过大(如响应超时)时,触发熔断,直接返回兜底数据(如默认值或旧数据),而不是让请求继续冲击数据库。在互斥锁方案中,也可以优化为:未抢到锁的请求不等待,直接返回降级数据,以此将“保护数据库”作为最高优先级。 二级缓存:在 Redis 之前再加一层本地缓存(如 Caffeine、Guava Cache)。热点数据在本地缓存中命中,几乎不产生网络开销,能极大地分担 Redis 和数据库的压力,作为整体的性能与稳定性兜底。 1.3 缓存雪崩 大量缓存数据同时过期或者Redis故障宕机的时候,大量的数据直接打到了数据库里,导致数据库压力增加。 过期时间加上随机值:在基础 TTL 上叠加一个随机偏移量,例如 TTL = 30分钟 + random(0~5分钟),让 Key 的失效时间分散开,避免同一时刻批量过期。这是最常用的基础方案。 分批过期 / 错峰预热:对于可预知会批量写入的缓存,不要一次性写入相同 TTL,而是按业务维度分批设置不同过期时间;系统启动或大促前预热时也分批加载,避免启动瞬间形成流量尖峰 热点数据永不过期 + 后台更新:对核心热点数据不设置物理 TTL,而是采用“逻辑过期 + 异步刷新”或定时任务主动刷新,从源头消除集中失效。这通常与击穿方案中的逻辑过期策略配合使用。 Redis高可用架构:使用哨兵模式实现主从自动故障转移,或使用 Redis Cluster 实现分片与高可用。避免单实例故障导致整个缓存层不可用。 多级缓存:在 Redis 之前增加本地缓存(如 Caffeine、Guava Cache),形成“本地缓存 → Redis → 数据库”的多级结构。即使 Redis 整体故障,本地缓存仍能承接一部分热点流量,为恢复争取时间。本地缓存适合存放极热、变化不频繁的数据。 持久化与快速恢复:合理配置 RDB/AOF,确保 Redis 重启后能较快恢复数据,缩短缓存层不可用窗口。同时要有容量规划和故障演练,避免恢复过程中再次被流量打垮。 熔断+限流+互斥锁+数据库层保护 二、Redis快照与恢复机制 2.1 AOF日志 Redis在执行完一条写命令后,就会把该命令追加写入一个文件中,在Redis重启时,会读取这些指令,然后逐一执行来进行数据恢复。 ...