一、Redis使用禁忌

Redis作为常驻内存的存储器,相对于常驻硬盘MySQL多了很多隐藏的禁忌,一不小心就会影响线上业务。
所以本手册会在最前面把所有的Redis使用禁忌列举出来。(禁忌是相对,特殊情况也可以打破禁忌)

1.阻塞

为什么会阻塞:

Redis作为高性能内存服务器在处理命令时为何使用单线程呢?
当单个线程任务运行时间过长时,我们常常用多线程技术,让其他线程处理其他的任务,从而不让其他任务阻塞等待,更快的跑完所有任务。
但是多线程会增加程序的复杂性。
如果单个线程任务运行时间很短,那么单线程也能很快的跑完所有任务。
由于Redis的数据存储在内存中,具有非常好的IO性能,通常情况下处理速度也很快,所以用单线程也具有很高的性能。
与此同时,Redis通过多路复用技术(epoll)尽可能多的接收请求命令,让所有命令排队一个个进入处理程序,进行处理。
也就是说Redis接收客户端请求如下图所示:
Redis服务端命令运行机制
正因为Redis的运行机制,所以当有命令运行时间很长时就会阻塞队列中的其他命令,照成其他命令一直等待。严重影响公司业务正常运行。

阻塞的危害:

a. 导致主从切换

那么哪些命令会导致Redis阻塞呢?

a. flushallflushdb

flushall会清空所有db的数据
flushdb会清空当前db的所有数据

害怕生产环境被经验不足的工程师误操作怎么办?
① 使用 rename-command将flushall和flushdb改为一个随机字符串
万一误操作了如何恢复呢?
① 如果AOF还没有重写,则在AOF中删除flushall或者flushdb
然后重新载入AOF即可
② 如果RDB还没有生成,马上备份RDB,然后载入RDB即可

b. keys

keys会一次性获取所有的Redis key,如果一个Redis实例中的key很多就会执行很久,阻塞其他命令执行。
所以生产环境禁止使用keys

如果需要去遍历key该怎么办呢?
① 用scan去迭代遍历,比如每次取50个
害怕生产环境被经验不足的工程师误操作怎么办?
① 使用 rename-command将keys改为一个随机字符串

c. hgetall
当一个hash很大时,hgetall会获取所有的field和value,照成阻塞

如果需要去遍历hash该怎么办呢?
① 用hscan去迭代遍历,比如每次取50个

d. del
当删除一个很大的hash、list、set、zset时,因为其中存储的内容需要循环释放,所以会阻塞

4.x版本可以使用unlink开启新线程异步删除,但是要注意复制线程所带来的内存开销和cpu开销,在内存和cpu有足够剩余空间时才能使用
最稳的方式还是下面几个
hash,可以使用hscan逐个删除
list,可以一个一个pop,或者使用LTRIM一次删除较少数据
set, 可以使用sscan逐个删除
zset,可以使用zscan逐个删除

e. sort

还有哪些原因会阻塞Redis线程呢
a. cpu饱和
cpu跑满,命令无法继续处理
b. 持久化阻塞
RDB和AOF重写时,需要fork当前线程,如果fork操作时间很长,就会阻塞主线程
AOF做fsync时,如果主线程发现距离上一次fsync成功超过2秒,为了数据安全性它会阻塞知道后台线程执行fsync操作完成。


dawnchengx
4 声望0 粉丝