【运维篇】5.4 Redis 并发延迟检测
文章目录
- 0.前言
- Redis工作原理
- 可能引起并发延迟的常见操作和命令
- 并发延迟检测
- 分析和解读监控数据:
- 优化并发延迟的策略
- 1. 检查CPU情况
- 2. 检查网络情况
- 3. 检查系统情况
- 4. 检查连接数
- 5. 检查持久化 :
- 6. 检查命令执行情况
0.前言
Redis 6.0版本之前其使用单线程模型处理所有命令。这意味着在给定的时间内,只有一个命令正在执行。虽然Redis非常快,每秒可以处理上万到十万个命令,但如果有一个命令需要大量的时间来执行,那么其他的命令就必须等待,这就是所谓的"并发延迟"。
并发延迟可能会导致应用程序的整体性能下降,因此对Redis的并发延迟进行检测和优化十分重要。尤其是在并发高、数据量大的生产环境中,及时地发现并解决潜在的并发延迟问题,对于保证Redis的性能和稳定性至关重要。
本篇博文将介绍Redis并发延迟的原因,以及如何检测并优化Redis的并发延迟。我们首先会解释Redis的工作原理,然后讨论一些可能引起并发延迟的常见操作和命令。接着,我们将讨论如何使用Redis自带的延迟监控功能进行并发延迟检测,以及如何分析和解读这些监控数据。最后,我们将提供一些实际的策略和建议,来帮助你优化Redis的并发延迟,提高Redis的性能和稳定性。
Redis工作原理
Redis 每个请求被接收后,Redis会将它放入一个队列中,然后顺序执行每个命令。这种模型的好处是避免了多线程并发访问数据时可能发生的冲突和锁的问题,但同时也意味着如果有一个命令执行时间过长,它会阻塞后面的所有命令。
可能引起并发延迟的常见操作和命令
- 大键操作:对于包含大量元素的列表、集合、有序集合或哈希等数据结构的操作可能会导致延迟。
- 慢查询:一些复杂的查询或计算密集型命令(如SORT、SUNION等)可能花费更长时间执行。
- 阻塞命令:某些命令(如BLPOP)在等待条件满足时会阻塞其他命令的执行。
- 持久化:如果使用RDB或AOF方式持久化数据,持久化操作可能会影响命令的执行。
并发延迟检测
Redis提供了一些内置的工具和命令来监控并发延迟:
SLOWLOG
命令:记录执行时间超过指定阈值的命令。INFO
命令:查看和分析Redis服务器的统计信息和性能指标。LATENCY MONITOR
特性:监控和报告Redis操作的延迟。
分析和解读监控数据:
SLOWLOG GET
:分析慢查询日志,找出执行时间过长的命令。INFO
命令的输出:查看特定的性能指标,例如每秒命令数、命中率、内存使用情况等。LATENCY MONITOR
:识别导致延迟的具体操作和时间点。
优化并发延迟的策略
- 优化数据结构:避免使用大键,合理设计数据结构。
- 限制慢查询:设置合理的超时阈值,对慢查询进行限制。
- 分片:将数据分布到多个Redis实例上,减轻单个实例的负担。
- 使用更快的持久化策略:如使用无磁盘同步等技术减少持久化操作对性能的影响。
- 硬件优化:升级硬件资源,如使用更快的CPU或增加内存。
- 避免阻塞命令:尽量避免使用会造成阻塞的命令,或将它们移到辅助线程中执行。
- 监控和调优:定期监控Redis的性能指标,根据监控数据调优配置。
1. 检查CPU情况
使用top
命令查看CPU使用情况。
top - 10:00:01 up 1 day, 2:43, 2 users, load average: 1.05, 0.70, 0.58
Tasks: 193 total, 2 running, 191 sleeping, 0 stopped, 0 zombie
%Cpu(s): 25.1 us, 1.4 sy, 0.0 ni, 73.0 id, 0.4 wa, 0.0 hi, 0.1 si, 0.0 st
KiB Mem : 16337836 total, 812508 free, 8736168 used, 6715160 buff/cache
KiB Swap: 2097148 total, 2097148 free, 0 used. 7106764 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
12345 redis 20 0 1.916g 1.800g 1020 S 99.9 11.4 22:10.82 redis-server
这里可以看到,redis-server
进程的CPU使用率接近100%,这表明可能需要垂直扩展。
也可以使用mpstat
mpstat
是一个展示CPU使用情况的工具,它可以显示所有CPU的统计信息,以及单个CPU的统计信息。命令mpstat -P ALL 1
的含义是显示所有CPU核心的性能统计数据,每隔1秒更新一次。以下是该命令的模拟输出:
Linux 4.15.0-123-generic (ubuntu) 12/02/2021 _x86_64_ (8 CPU)
10:01:01 AM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
10:01:02 AM all 3.50 0.00 1.25 0.75 0.00 0.12 0.00 0.00 0.00 94.38
10:01:02 AM 0 7.00 0.00 1.00 2.00 0.00 0.00 0.00 0.00 0.00 90.00
10:01:02 AM 1 2.00 0.00 1.50 0.00 0.00 0.50 0.00 0.00 0.00 96.00
10:01:02 AM 2 3.00 0.00 1.00 1.00 0.00 0.00 0.00 0.00 0.00 95.00
10:01:02 AM 3 4.00 0.00 2.00 0.00 0.00 0.00 0.00 0.00 0.00 94.00
10:01:02 AM 4 3.00 0.00 1.00 1.00 0.00 0.00 0.00 0.00 0.00 95.00
10:01:02 AM 5 3.00 0.00 1.00 0.50 0.00 0.50 0.00 0.00 0.00 95.00
10:01:02 AM 6 4.00 0.00 2.00 0.50 0.00 0.50 0.00 0.00 0.00 93.00
10:01:02 AM 7 3.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00 0.00 96.00
每一行表示一个CPU的统计数据,包括用户空间(%usr)、优先级更低的进程(%nice)、系统空间(%sys)等等。最后一列是空闲时间(%idle)。
2. 检查网络情况
使用netstat
命令检查Redis端口的网络情况。
netstat -nlt | grep 6379
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN
tcp6 0 0 ::1:6379 :::* LISTEN
这里显示了本机6379端口正在监听网络连接。
3. 检查系统情况
使用vmstat
命令检查系统资源情况。
vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 0 812508 12345 6715160 0 0 12 45 342 1234 25 1 73 0 0
...
Redis 本身并不提供直接的命令来检查网络情况,但可以通过几种方式来评估Redis服务的网络性能或连接状态。
PING
命令:这是Redis的一个基础命令,用于检查服务是否运行并能响应命令。
PING
如果服务运行正常,将得到一个PONG
响应。
INFO
命令:这个命令提供了Redis服务器和其客户端的详细信息,包括网络相关的统计数据。比如:
INFO replication
INFO stats
这些子命令会显示连接和同步的信息,以及执行的命令数量等。
CLIENT LIST
命令:这个命令会展示所有连接到Redis服务器的客户端列表及其相关的信息,包括地址、端口、连接时长、空闲时间等。
CLIENT LIST
- 网络工具:除了Redis命令,还可以使用标准的网络工具来检测与Redis服务的连接情况。比如
ping
命令检查网络延迟,telnet
或nc
(netcat)尝试连接到Redis服务端口,traceroute
或tracert
(在Windows上)来追踪数据包路径。
ping <redis-server-ip>
telnet <redis-server-ip> <redis-port>
nc -vz <redis-server-ip> <redis-port>
traceroute <redis-server-ip>
MONITOR
命令:尽管这并非直接检查网络情况的命令,但它允许监视实时的Redis服务器接收到的命令,可以帮助理解Redis服务器的负载情况。
MONITOR
如果发现Redis的响应时间长或连接数异常,可能是网络延迟、带宽限制、过载或其他网络问题。在这种情况下,检查的网络配置、防火墙规则和硬件设备可能会很有帮助。
在Redis中,你可以使用以下命令检查系统的状态和性能:
INFO
命令:这个命令提供了关于Redis服务器的各种信息和统计,包括内存使用、CPU使用、客户端连接、数据库统计等。
INFO
这会返回一系列的信息。对于系统和网络的检查,你可能会对这部分感兴趣:
used_memory
: 用于表示Redis分配的内存总量,以字节(bytes)为单位。used_memory_human
: 以更易读的格式展示Redis分配的内存总量(如KB、MB、GB)。connected_clients
: 已连接客户端的数量。instantaneous_ops_per_sec
: Redis当前的qps,即每秒的查询次数。
SLOWLOG
命令:这个命令可以帮你找到那些执行时间较长的命令。你可以使用SLOWLOG GET
来获取慢查询日志的内容,使用SLOWLOG LEN
来获取慢查询日志的长度,使用SLOWLOG RESET
来清空慢查询日志。
SLOWLOG GET
SLOWLOG LEN
SLOWLOG RESET
4. 检查连接数
使用redis-cli info
命令查看Redis的连接数。模拟输出可能如下:
redis-cli info | grep connected_clients
connected_clients:10
显示当前有10个客户端连接到Redis服务器。
5. 检查持久化 :
使用redis-cli info
命令检查Redis持久化情况。
redis-cli info | grep rdb_last_bgsave_status
rdb_last_bgsave_status:ok
显示最后一次背景保存(bgsave)的状态是成功的。
在Redis中,最常用的持久化方式有RDB和AOF,可以通过INFO persistence
命令查看相关的持久化信息。
对于RDB持久化,latest_fork_usec
字段显示上一次执行fork操作的持续时间,单位为微秒。这通常在Redis每次执行RDB或AOF重写时发生。
以下是INFO persistence
命令的一些输出示例:
# Persistence
loading:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1626293675
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:2498560
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:0
其中,关于RDB的一些关键字段解释如下:
rdb_changes_since_last_save
: 自上次成功生成RDB文件后,Redis服务器接收到的写命令数量。rdb_bgsave_in_progress
: 如果服务器正在创建RDB文件,那么值为1,否则为0。rdb_last_save_time
: 服务器最后一次成功执行SAVE
或BGSAVE
命令的Unix时间戳。rdb_last_bgsave_status
: 最后一次BGSAVE
命令的执行状态,成功为ok,失败为err。rdb_last_bgsave_time_sec
: 最后一次成功执行BGSAVE
命令耗费的时长,以秒为单位。
同样,你也可以通过CONFIG GET save
命令查看RDB的触发条件,该命令返回的结果形式如下:
1) "save"
2) "900 1 300 10 60 10000"
上述结果表示,当以下任一条件满足时,Redis会自动触发BGSAVE
命令:
- 900秒内有1个key发生变更
- 300秒内有10个key发生变更
- 60秒内有10000个key发生变更
6. 检查命令执行情况
使用redis-cli monitor
命令查看Redis命令执行的实时情况。
redis-cli monitor
1614092587.248133 [0 127.0.0.1:6379] "set" "key1" "value1"
1614092587.251993 [0 127.0.0.1:6379] "get" "key1"
检查Redis中每个命令的执行情况可以通过INFO commandstats
命令,这个命令提供了关于Redis服务器上每个命令执行的统计数据。
INFO commandstats
执行上述命令,Redis将返回各种命令及其相关统计信息。返回的结果形式如下:
cmdstat_get:calls=100,usec=700,usec_per_call=7.00
cmdstat_set:calls=50,usec=300,usec_per_call=6.00
cmdstat_del:calls=20,usec=200,usec_per_call=10.00
在上面的输出中,每一行表示一个命令的统计信息:
cmdstat_get
,cmdstat_set
,cmdstat_del
分别代表get
,set
,del
这三个命令的统计数据。calls
字段表示该命令被调用的次数。usec
字段表示该命令总的执行时间,以微秒为单位。usec_per_call
字段表示该命令每次执行的平均时间,以微秒为单位。