乐趣区

Redis使用手册 – 基础篇

一、Redis 使用禁忌
Redis 作为常驻内存的存储器,相对于常驻硬盘 MySQL 多了很多隐藏的禁忌,一不小心就会影响线上业务。所以本手册会在最前面把所有的 Redis 使用禁忌列举出来。(禁忌是相对,特殊情况也可以打破禁忌)
1. 阻塞
为什么会阻塞:
Redis 作为高性能内存服务器在处理命令时为何使用单线程呢?当单个线程任务运行时间过长时,我们常常用多线程技术,让其他线程处理其他的任务,从而不让其他任务阻塞等待,更快的跑完所有任务。但是多线程会增加程序的复杂性。如果单个线程任务运行时间很短,那么单线程也能很快的跑完所有任务。由于 Redis 的数据存储在内存中,具有非常好的 IO 性能,通常情况下处理速度也很快,所以用单线程也具有很高的性能。与此同时,Redis 通过多路复用技术(epoll)尽可能多的接收请求命令,让所有命令排队一个个进入处理程序,进行处理。也就是说 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 操作完成。

退出移动版