Redis的删库与跑路
Redis作为最流行的内存数据库之一,几乎每个公司都对其有所依赖.而大家都会注意的问题是”mysql库的删库与跑路”,很容易忽略redis这个依赖性非常高的中间件,一旦出问题,势必对整个业务甚至整个公司有影响.
举个例子:
redis是单线程数据库,如果一个命令执行时间很长,很容易造成请求挤压,进而会造成请求的大量超时,系统熔断,业务崩溃,甚至雪崩.
再比如redis数据被误删了,缓存击穿,压垮数据库,系统雪崩.
如果redis存储的是业务处理结果或者作为队列等使用,后果会更严重.
redis危险命令
罪不在枪,而在于扣动扳机的人
这些命令确实在一定情况下会产生危害,但只要使用的合理是可以给我们很多帮助的.
1. key查找命令: keys *
因为redis是单线程的,keys操作会使其他的请求都会被堵塞,对于数据量较小时,基本没有影响;但是当数据量达到百万千万级别的时候,这个会造成数据库崩溃,使用的业务崩溃,引起雪崩.
2. 清空数据库: flushdb
清空所有记录: flushall
3. 服务关机: shutdown
4. 数据库互相交换swapdb
swapdb 0 1 这将使数据库0与数据库1交换
5. 数据持久化: save
数据持久化操作,生成rdb文件,并对键进行检查,过期键过滤掉,这时系统会被阻塞,不能接受处理客户端命令
6. 系统配置项查看修改: config
6.1 修改日志级别产生大量日志
127.0.0.1:6379> config get loglevel
1) "loglevel"
2) "notice"
127.0.0.1:6379> config set loglevel "debug"
ok
127.0.0.1:6379> config get loglevel
1) "loglevel"
2) "debug"
6.2 修改服务密码,所有链接全部无法正常请求,系统崩溃
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) ""
127.0.0.1:6379> config set requirepass foobar
ok
127.0.0.1:6379> config get requirepass
(error) noauth authentication required.
127.0.0.1:6379> auth foobar
ok
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) "foobar"
127.0.0.1:6379>
7. lua脚本相关命令: eval, evalsha, script
8. 调试命令:debug
这个命令不全都包含危险选项,也有很多有用的调试选项.
8.1 危险选项
8.1.1 debug oom
极度危险命令,申请一大片内存,直接让zmalloc触发oom错误,造成服务崩溃.
8.1.2 debug reload
保存rdb文件,清空当前数据库,重新加载rdb,加载与启动时加载类似,加载过程中只能服务部分只读请求(比如info,ping等)
8.1.3 debug loadaof
清空当前数据库,重新从aof文件里加载数据库
8.1.4 debug sleep
模拟一个需指定执行时间开销的命令
debug sleep 0.1相当于执行了一条开销为100ms的命令.
8.2 调试选项
8.2.1 debug digest
对整个数据库的数据,产生一个摘要,验证两个redis数据库数据是否一致.
8.2.2 debug object
查看key的数据类型等基本信息
127.0.0.1:6379> set key a
ok
127.0.0.1:6379> debug object key
value at:0x7f6701d2fe70 refcount:1 encoding:embstr serializedlength:2 lru:10152892 lru_seconds_idle:10
8.2.3 debug populate
快速产生大量的key
127.0.0.1:6379> debug populate 1000
ok
127.0.0.1:6379> dbsize
(integer) 1000
如何保护你的redis
这些命令就像达摩克利斯之剑,让人战战兢兢,压力倍增.
那该如何解决呢?
1. keys命令的优化
1.1 randomkey
随机返回一个key,在数据量非常多的时候,可以初步观察库中key的构成情况.
1.2 scan
使用如下命令,相当于keys *命令
scan 0 match * count 3
配合游标,匹配正则,返回总数可以很方便的查询想要的结果.
2. save的优化
使用bgsave命令代替save命令做数据持久化.
bgsave命令会 fork 出一个子进程,子进程负责持久化rdb文件,并在保存完成之后向主进程发送信号,通知保存已完成.redis 服务器在bgsave执行期间仍然可以继续处理客户端的请求.
3. 其他命令
对应flushdb,flushall,shutdown等命令,并没有合适的替代命令,但可以通过配置文件禁用和重命名命令
redis.conf 文件中有security 选项处,有rename-command配置.
#命令禁用
rename-command keys ""
rename-command flushall ""
rename-command flushdb ""
#命令重命名
rename-command config config_proxy
127.0.0.1:6380> flushall
(error) err unknown command `flushall`, with args beginning with:
127.0.0.1:6380>
127.0.0.1:6380>
127.0.0.1:6380> keys *
(error) err unknown command `keys`, with args beginning with: `*`,
127.0.0.1:6380>
127.0.0.1:6380>
127.0.0.1:6380> config get *
(error) err unknown command `config`, with args beginning with: `get`, `*`,
127.0.0.1:6380> config_proxy get *
1) "dbfilename"
2) "dump.rdb"
3) "requirepass"
4) ""
5) "masterauth"
6) ""
在使用rename-command配置时,redis还有一段提示信息要注意.
please note that changing the name of commands that are logged into theaof file or transmitted to slaves may cause problems.
这段信息的意思是:如果重命名的命令会存入在aof文件中,或者如果该重命名命令需传输到slave服务,而slave服务未进行相关配置,则会引起问题.
所以,处理重命名的最佳方法是确保将重命名命令应用于主从安装中的所有实例中.
请记住,一旦有人登录到您的服务器,就很容易规避我们已部署的redis特定的安全功能,所以防火墙很重要;
祸起萧墙,操作规范也非常重要,不要真的变成了删库跑路.
推荐阅读
(长按二维码即可关注)