快速导航
Redis不可不知的故障现象
一、缓存雪崩
定义:
由缓存机器故障宕机,导致大量请求全部落到数据库,超出了数据库的处理能力极限,进而导致数据库压力增大、宕机的情况。
解决方案:
- 事前:Redis集群部署,主从+哨兵,避免全盘奔溃
- 事中:本地缓存 + 限流&降级,避免数据库压力过大宕机
- 事后:Redis持久化,机器重启后可以自动从磁盘加载数据,恢复缓存数据
二、缓存穿透
定义:
大批量请求缓存和数据库中都不存在的数据,导致数据库压力变大,甚至宕机。
解决方案一:
查询的key比较集中的时候,可以在查询数据库结束后给缓存中写一个空值或者默认值进去。设置一个过期时间,避免后续的大量请求落到数据库。
解决方案二(更普遍的做法):
在系统和缓存之间使用布隆过滤器,将数据库中所有可能的数据哈希映射到布隆过滤器中。
在请求到布隆过滤器时判断:
- 若请求数据的key不存在布隆过滤器中,直接返回不存在(可以确定该数据也一定不存在于数据库)
- 若请求数据的key在布隆过滤器中存在,则继续查询缓存
三、缓存击穿
定义:
某个热点key访问非常频繁,且请求时间比较集中,是高并发场景。当这个key失效的瞬间,大量的请求直接落到数据库,导致数据库压力骤增,甚至宕机。
解决方案:
- 基本不更新的热点数据,设置为永不过期
- 更新不频繁且缓存刷新流程耗时较少的情况下,可以基于互斥锁保证较少量的请求落到数据库,并重新构建缓存,而其他线程在锁释放后可访问新缓存。
- 缓存数据更新频繁或者缓存刷新耗时较长的情况下,可以利用设置定时任务在任务过期前主动重新构建缓存或延后过期时间,以保证请求能一直访问到缓存
四、缓存失效
Redis缓存失效的情况:
1. 过期时间到期:
-
Redis缓存可以设置过期时间,当缓存的过期时间到达后,缓存数据会自动失效。
-
解决方案: 合理设置缓存的过期时间,避免缓存数据过早或过晚失效。同时,可以考虑使用动态过期时间策略,根据数据的实际使用情况调整过期时间。
2. 内存不足:
- 当Redis的内存使用达到上限时,Redis会根据配置的淘汰策略(如LRU算法)自动删除部分缓存数据,以释放内存空间。
- 解决方案: 监控Redis的内存使用情况,及时升级Redis的内存配置或优化缓存策略,如减少不必要的缓存数据、增加缓存的复用率等。
3. 手动删除:
- 管理员或开发者可能会通过Redis客户端命令手动删除缓存数据。
- 解决方案: 建立规范的缓存操作流程,确保只有授权人员才能对缓存进行删除操作。同时,可以通过日志记录缓存的删除操作,以便追溯和审计。
4. 服务器重启:
- Redis服务器重启时,所有缓存数据会丢失(除非使用了持久化功能)。
- 解决方案: 配置Redis的持久化功能(如RDB或AOF),确保在服务器重启后能够恢复缓存数据。
5. 数据更新:
- 当缓存数据对应的数据库数据发生更新时,如果缓存没有及时更新,就会导致缓存失效。
- 解决方案: 实现缓存与数据库数据的一致性同步机制,如使用消息队列或订阅数据库变更日志来实时更新缓存数据。
6. 分布式环境下的缓存失效:
- 在分布式系统中,多个应用节点可能同时使用同一个Redis缓存。如果某个节点修改了缓存数据,其他节点的缓存可能会失效。
- 解决方案: 使用分布式锁或其他同步机制来确保在分布式环境下缓存数据的一致性。
7. 缓存雪崩:
- 当大量缓存数据同时失效时,大量请求会涌入数据库,可能导致系统崩溃。
- 解决方案: 设置随机过期时间以避免缓存同时失效;使用多级缓存策略;实施缓存标记策略;通过主从复制和哨兵机制提高Redis的高可用性;使用第三方插件如RocketMQ自动更新缓存等。
解决方案总结
- 合理设置缓存过期时间:根据数据的实际使用情况设置合理的过期时间。
- 监控和优化内存使用:定期监控Redis的内存使用情况,并优化缓存策略以减少内存消耗。
- 规范缓存操作:建立规范的缓存操作流程,确保只有授权人员才能对缓存进行删除等操作。
- 配置持久化功能:启用Redis的持久化功能,确保在服务器重启后能够恢复缓存数据。
- 实现缓存与数据库的一致性同步:通过消息队列或订阅数据库变更日志等方式实现缓存与数据库数据的一致性同步。
- 应对分布式环境下的缓存失效:使用分布式锁或其他同步机制来确保缓存数据的一致性。
- 防范缓存雪崩:采取多种策略来避免缓存雪崩的发生,如设置随机过期时间、使用多级缓存、实施缓存标记策略等。
五、热点缓存重建
1. 预热机制
- 定义:在系统启动或重启时,提前将预测会频繁访问的热点数据加载到缓存中。
- 实现方式:
- 通过定时任务在系统启动时执行数据加载。
- 利用系统启动时的初始化代码加载数据。
- 通过模拟请求或默认请求来预热缓存。
- 优势:避免了系统启动初期的缓存穿透问题,提高了系统的启动速度和稳定性。
2. 异步重建
- 定义:当热点缓存失效时,不立即阻塞请求线程去重建缓存,而是通过异步任务或消息队列等方式来重建缓存。
- 实现方式:
- 在缓存失效时,发布一个缓存失效事件到消息队列。
- 系统中设置一个监听器来监听这些事件,一旦监听到失效事件,就启动一个异步线程去重建缓存。
- 异步线程可以从数据库中获取数据,并将数据写回缓存。
- 优势:降低了对系统实时性能的影响,使系统能够平滑处理高并发请求。
3. 分布式锁
- 定义:在缓存重建过程中,使用分布式锁来确保同一时间只有一个线程或进程在重建缓存。
- 实现方式:
- 当缓存失效时,尝试获取分布式锁。
- 如果获取锁成功,则进行缓存重建操作;如果获取锁失败,则等待或重试。
- 缓存重建完成后,释放分布式锁。
- 优势:避免了多个线程或进程同时重建缓存导致的资源浪费和竞态条件。
4. 缓存预热与更新策略
- 策略一:在系统启动或业务低峰期,通过预热机制加载热点数据。
- 策略二:定期更新缓存中的热点数据,确保数据的新鲜度。可以使用定时任务或监控机制来触发更新操作。
- 策略三:根据缓存的访问频率和数据的变化情况,动态调整缓存的过期时间和重建策略。
5. 缓存降级与容错
- 缓存降级:在缓存重建过程中,如果发生错误或异常,可以实施缓存降级策略,如返回默认值、空值或缓存中的旧数据,以避免系统崩溃。
- 容错机制:确保缓存系统具有容错能力,能够在遇到硬件故障、网络问题等异常情况时,仍能提供一定程度的服务。
6. 其他考虑因素
- 数据一致性:在缓存重建过程中,需要确保缓存数据与数据库数据的一致性。可以采用双写、延时双删或订阅数据库变更日志等方式来实现。
- 性能监控:对缓存的访问情况、命中率、重建时间等进行实时监控,以便及时发现并解决潜在的性能问题。