Redis 是一种内存数据库,将数据保存在内存中,读写效率要比传统的将数据保存在磁盘上的数据库要快很多。但是 Redis 也会发生延迟时,这是就需要我们对其产生原因有深刻的了解,以便于快速排查问题,解决 Redis的延迟问题
一条命令执行过程
在本文场景下,延迟 (latency) 是指从客户端发送命令到客户端接收到命令返回值的时间间隔。所以我们先来看一下 Redis 一条命令执行的步骤,其中每个步骤出问题都可能导致高延迟。

上图是 Redis 客户端发送一条命令的执行过程示意图,绿色的是执行步骤,而蓝色的则是可能出现的导致高延迟的原因。
网络连接限制、网络传输速率和 CPU 性能等是所有服务端都可能产生的性能问题。但是 Redis 有自己独有的可能导致高延迟的问题:命令或者数据结构误用、持久化阻塞和内存交换。
而且更为致命的是,Redis 采用单线程和事件驱动的机制来处理网络请求,分别有对应的连接应答处理器,命令请求处理器和命令回复处理器来处理客户端的网络请求事件,处理完一个事件就继续处理队列中的下一个。一条命令处理出现了高延迟会影响接下来处于排队状态的其他命令。

对于高延迟,Redis 原生提供慢查询统计功能,执行 slowlog get {n} 命令可以获取最近的 n 条慢查询命令,默认对于执行超过 10 毫秒(可配置)的命令都会记录到一个定长队列中,线上实例建议设置为 1 毫秒便于及时发现毫秒级以上的命令。
-
# 超过 slowlog-log-slower-than 阈值的命令都会被记录到慢查询队列中
-
# 队列最大长度为 slowlog-max-len
-
slowlog-log-slower-than 10000
-
slowlog-max-len 128
如果命令执行时间在毫秒级,则实例实际 OPS 只有 1000 左右。慢查询队列长度默认 128,可适当调大。慢查询本身只记录了命令执行时间,不包括数据网络传输时间和命令排队时间,因此客户端发生阻塞异常 后,可能不是当前命令缓慢,而是在等待其他命令执行。需要重点比对异常和慢查询发生的时间点,确认是否有慢查询造成的命令阻塞排队。
slowlog 的输出格式如下所示。第一个字段表示该条记录在所有慢日志中的序号,最新的记录被展示在最前面;第二个字段是这条记录被记录时的系统时间,可以用 date 命令来将其转换为友好的格式第三个字段表示这条命令的响应时间,单位为 us (微秒);第四个字段为对应的 Redis 操作。
> slowlog get
1) 1) (integer) 26
2) (integer) 1450253133
3) (integer) 43097
4) 1) "flushdb"
不合理的命令或者数据结构
> redis-cli -h host -p 12345 --bigkeys
# Scanning the entire keyspace to find biggest keys as well as # average sizes per key type. You can use -i 0.1 to sleep 0.1 sec # per 100 SCAN commands (not usually needed). [00.00%] Biggest hash found so far 'idx:user' with 1 fields [00.00%] Biggest hash found so far 'idx:product' with 3 fields [00.00%] Biggest hash found so far 'idx:order' with 14 fields [02.29%] Biggest hash found so far 'idx:fund' with 16 fields [02.29%] Biggest hash found so far 'idx:pay' with 69 fields [04.45%] Biggest set found so far 'indexed_word_set' with 1482 members [05.93%] Biggest hash found so far 'idx:address' with 159 fields [11.79%] Biggest hash found so far 'idx:reply' with 196 fields -------- summary ------- Sampled 1484 keys in the keyspace! Total key length in bytes is 13488 (avg len 9.09) Biggest set found 'indexed_word_set' has 1482 members Biggest hash found 'idx:的' has 196 fields 0 strings with 0 bytes (00.00% of keys, avg size 0.00) 0 lists with 0 items (00.00% of keys, avg size 0.00) 2 sets with 1710 members (00.13% of keys, avg size 855.00) 1482 hashs with 6731 fields (99.87% of keys, avg size 4.54) 0 zsets with 0 members (00.00% of keys, avg size 0.00)

> redis-cli -c -p 7000 info | grep -w latest_fork_usec
latest_fork_usec:315
Asynchronous AOF fsync is taking too long (disk is busy).
Writing the AOF buffer without waiting for fsync to complete,
this may slow down Redis.
也可以查看 info persistence 统计中的 aofdelayedfsync 指标,每次发生 fdatasync 阻塞主线程时会累加。
>info persistence
loading:0
aof_pending_bio_fsync:0
aof_delayed_fsync:0
内存交换
>redis-cli -p 6383 info server | grep process_id # 查询 redis 进程号
>cat /proc/4476/smaps | grep Swap # 查询内存交换大小
Swap: 0 kB
Swap: 4 kB
Swap: 0 kB
Swap: 0 kB
-
保证机器充足的可用内存 -
确保所有 Redis 实例设置最大可用内存(maxmemory),防止极端情况下 Redis 内存不可控的增长。 -
降低系统使用 swap 优先级,如 echo10>/proc/sys/vm/swappiness。
转自:博客园 作者:程序员小冰
www.cnblogs.com/remcarpediem/p/11845065.html