目录

一、问题描述

二、改进方案

1、流程规范

2、SCAN命令

3、使用scan命令批量删除

三、小结


一、问题描述

听说有个老哥在Redis中执行了一条命令导致服务宕机,老大说:谁再用redis 的 keys命令,立刻给我走人....

先看现象:

redis-cli keys * | args redis-cli del
(error) ERR network error
(30.00s)

什么???执行了一条 keys xxxxx* 命令,令数据库宕机了。

上面这条keys 模糊的匹配命令看着是为了清理没用的键,但是没有考虑到keys *进行模糊匹配引发 Redis 锁,造成 Redis 锁住,CPU 飙升,引起了所有调用链路的超时并且卡住,等 Redis 锁的那几秒结束,所有的请求流量全部请求到 RDS 数据库中,使数据库产生了雪崩,使数据库宕机。

二、改进方案

1、流程规范

  • 所有线上操作,全部要经过运维通过后方可执行,运维部门逐步快速收回各项权限
  • 新增 Redis 实例,进行分离
  • 如果有使用类似 keys 正则命令需求,使用 scan 命令代替

2、SCAN命令

Redis从2.8版本开始支持scan命令,SCAN命令的基本用法如下:

  • 复杂度虽然也是 O(n),通过游标分步进行不会阻塞线程
  • 有限制参数 COUNT
  • 同 keys命令 一样提供模式匹配功能
  • 服务器不需要为游标保存状态,游标的唯一状态就是 scan 返回给客户端的游标整数

使用示例:模糊匹配share2me,返回前100个

scan 0 match share2me* count 100

3、使用scan命令批量删除

因为KEYS命令的时间复杂度为O(n),而SCAN命令会将遍历操作分解成m次,然后每次去执行,从而时间复杂度为O(1)。也解决使用keys命令遍历大量数据而导致Redis服务器阻塞的情况。所以建议使用下边的指令进行批量的删除操作:

redis-cli --scan --pattern "key的前缀*" | xargs -L 1000 redis-cli del

三、小结

因为Redis的KEYS在某种情况下会阻塞。在生产环境中一定要慎用慎用,有个真实真案件小哥哥生产用KEYS,最终导致服务宕机。后果很严重,产生的经济损失就不说了。

切记严重会导致程序的雪崩,删除的时候用SCAN命令。