当前位置:首页 > 问答 > 正文

Redis集群缓存怎么清理才靠谱,实操技巧和注意点全解析

关于如何靠谱地清理Redis集群缓存,这确实是一个在实际运维中经常会遇到且需要谨慎处理的问题,如果操作不当,很容易引发数据库雪崩、系统性能骤降甚至服务不可用等严重故障,下面将结合一些常见的实践经验,来详细解析其中的技巧和注意点。

核心原则:永远避免在业务高峰期进行大规模清理

这是最首要也是最关键的一点,无论你采用哪种清理方法,在业务流量高峰时段执行,都相当于主动制造一场“缓存地震”,因为大量缓存瞬间消失,会导致所有请求直接涌向后端数据库(如MySQL),数据库很可能因为无法承受突如其来的巨大压力而崩溃,进而导致整个系统瘫痪,清理操作必须选择在凌晨等业务量最低的时间窗口进行。

使用 FLUSHALL 命令及其风险

最直接的清理方式是使用Redis提供的 FLUSHALL 命令,在集群模式下,这个命令需要加上 ASYNC 选项,即 FLUSHALL ASYNC。(来源:Redis官方文档关于 FLUSHALL 命令的说明)ASYNC 的意思是异步执行,它会立即返回OK,然后在后台线程中逐步清理所有数据,这比同步的 FLUSHALL 要好,因为同步命令会阻塞整个Redis节点,直到所有数据删除完毕,期间无法响应任何其他请求,风险极高。

但即便使用 ASYNCFLUSHALL 的风险依然非常大:

Redis集群缓存怎么清理才靠谱,实操技巧和注意点全解析

  1. 数据全部丢失:它会清空整个集群的所有数据,是不可逆的,如果你只想清理某个特定业务的数据,它就无能为力了。
  2. 性能冲击:虽然异步非阻塞,但大规模删除操作本身会消耗大量的CPU和内存资源,可能会影响集群在同一时间段内处理正常请求的性能。
  3. 缓存雪崩:清理完成后,所有Key都不存在了,重启的业务流量会像海啸一样直接拍向数据库。

FLUSHALL 通常只适用于测试环境、极端紧急情况(如被注入恶意数据)或能够确保后端数据库绝对扛得住冲击的场景。

更推荐的渐进式清理——使用 SCANDEL

对于生产环境,更稳妥、更常用的方式是进行“渐进式”或“模式化”清理,也就是只删除那些符合特定模式的Key,比如以 "product_cache:" 开头的所有商品缓存。

Redis集群缓存怎么清理才靠谱,实操技巧和注意点全解析

具体操作步骤是:

  1. 连接上集群中的任意一个节点
  2. 使用 SCAN 命令迭代地查找所有匹配的Key,切记,绝对不要使用 KEYS 命令!(来源:Redis官方警告)因为 KEYS 命令会一次性遍历所有Key,在数据量大的情况下会长时间阻塞Redis,导致服务卡顿,而 SCAN 命令是分批次、游标方式的,对服务器影响极小。
  3. 对找到的每一个Key,使用 DEL 命令进行删除

你可以写一个简单的脚本来完成这个工作,用Shell脚本结合Redis-cli的示例如下:

#!/bin/bash
cursor=0
pattern="your_cache_prefix:*" # 替换成你实际要删除的Key模式
redis_node="your_redis_host:port" # 替换成集群中一个节点的地址
while [[ $cursor -ne 0 ]] || [[ $cursor -eq 0 ]]; do
  # 使用SCAN命令,每次获取一批Key
  reply=$(redis-cli -c -h ${redis_node%:*} -p ${redis_node#*:} SCAN $cursor MATCH "$pattern" COUNT 100)
  # 解析回复,得到新的游标和Key列表
  cursor=$(echo "$reply" | head -n1)
  keys=$(echo "$reply" | tail -n +2)
  # 如果有关键词,则逐个删除
  if [[ -n $keys ]]; then
    echo "$keys" | while read key; do
      if [[ -n $key ]]; then
        # 使用DEL命令删除,-c表示以集群模式运行
        redis-cli -c -h ${redis_node%:*} -p ${redis_node#*:} DEL "$key"
        echo "Deleted: $key"
      fi
    done
  fi
  # 如果游标回到0,表示迭代结束
  if [[ $cursor -eq 0 ]]; then
    break
  fi
done

这种方法的优点非常明显

  • 精准打击:只清理需要清理的数据,不影响其他业务的缓存。
  • 平滑过渡:删除操作是分批进行的,对Redis服务器和后台数据库的压力是逐步释放的,大大降低了引发雪崩的风险。
  • 可控性强:你可以通过调整 COUNT 参数(比如每次扫描100个或500个Key)来控制每次处理的批量大小,还可以在脚本中增加 sleep 间隔,让删除的节奏更慢,对系统更友好。

重要的注意点和补充技巧

  1. 设置过期时间(TTL)是治本之策:与其手动清理,不如在设置缓存时就为其设置合理的过期时间(TTL),让缓存自动失效,这是最优雅、对系统无感的方式,手动清理更多是用于处理异常或进行主动刷新。
  2. 清理前务必确认Key模式:在执行删除脚本前,最好先用 SCAN 命令预览一下匹配到的Key列表,确认模式是否正确,避免误删。
  3. 关注删除期间的系统监控:在执行渐进式删除的过程中,务必密切监控Redis集群的CPU、内存使用率、网络流量,以及后端数据库的连接数、QPS、慢查询等关键指标,一旦发现数据库压力过大,可以随时暂停或放慢脚本的执行速度。
  4. 考虑使用 UNLINK 替代 DEL:(来源:Redis 4.0版本新特性)从Redis 4.0开始,提供了 UNLINK 命令,它与 DEL 的区别在于,UNLINK 是异步删除,它会先将Key从Keyspace中移除,然后再在后台线程中回收内存,这对于删除非常大的Key或大批量Key时尤其有用,可以避免删除操作阻塞主线程,在上述脚本中,可以将 DEL 直接替换为 UNLINK

清理Redis集群缓存没有一刀切的最佳方案,关键在于“谨慎”和“平滑”,优先通过设置TTL让缓存自动管理,必要时采用基于 SCANUNLINK 的渐进式模式化删除,并严格在低峰期操作且辅以全程监控,这才是最靠谱的实操之道。