8.5.3 命令与慢查询优化
命令与慢查询优化#
本节聚焦 Redis 命令使用与慢查询治理,目标是在不破坏业务语义的前提下,降低单条命令耗时与阻塞风险,稳定延迟并提升吞吐。
1. 慢查询体系与识别#
原理草图(命令进入与慢日志记录)
关键配置与查看
- slowlog-log-slower-than:慢查询阈值(微秒)
- slowlog-max-len:慢日志队列长度
示例:配置与查看慢日志
# 1) 查看当前慢日志配置
redis-cli CONFIG GET slowlog-log-slower-than
redis-cli CONFIG GET slowlog-max-len
# 2) 临时修改阈值为 5ms(5000微秒)
redis-cli CONFIG SET slowlog-log-slower-than 5000
redis-cli CONFIG SET slowlog-max-len 256
# 3) 触发慢命令示例(模拟慢操作)
redis-cli EVAL "redis.call('SET','k','v'); for i=1,100000 do end" 0
# 4) 查看慢日志
redis-cli SLOWLOG GET 10
# 预期:SLOWLOG 返回包含耗时(microseconds)与命令参数
识别流程(可操作命令)
# 1) 获取慢日志
redis-cli SLOWLOG GET 128 > /tmp/redis_slowlog.txt
# 2) 查看命令统计与耗时
redis-cli INFO commandstats | egrep 'cmdstat_(get|set|mget|zrange|hgetall)'
# 3) 结合延迟监控
redis-cli --latency -h 127.0.0.1 -p 6379
2. 高成本命令与替代策略#
示例:KEYS 替代为 SCAN
# 危险命令(阻塞):KEYS user:*
# 替代:SCAN 分批遍历
redis-cli --scan --pattern 'user:*' | head -n 20
示例:大集合遍历替代
# 危险:SMEMBERS big_set
# 替代:SSCAN 分批拉取
redis-cli SSCAN big_set 0 COUNT 100
示例:避免大范围 LRANGE
# 危险:LRANGE list 0 -1
# 替代:分页拉取
redis-cli LRANGE list 0 199
redis-cli LRANGE list 200 399
命令解释
- SCAN/SSCAN/HSCAN/ZSCAN:游标式遍历,不阻塞主线程
- COUNT:每次返回元素数量提示,非强保证
3. 热点 Key 与大 Key 治理#
定位热点 Key 示例
# 1) 统计热点命令调用
redis-cli INFO commandstats | sort -t=, -k2 -nr | head -n 5
# 2) 查看单 key 大小
redis-cli MEMORY USAGE user:profile:10001
定位大 Key 示例
# 扫描大 key(会遍历全库,建议低峰执行)
redis-cli --bigkeys
治理实践(示例)
# 大 key 拆分:将 user:profile:10001 拆为 user:profile:10001:partN
# 示例:拆分哈希字段
redis-cli HSET user:profile:10001:part1 name "alice"
redis-cli HSET user:profile:10001:part2 bio "..."
4. 命令执行成本优化要点#
示例:批量与 Pipeline
# 1) 单条写入(多 RTT)
redis-cli SET k1 v1
redis-cli SET k2 v2
# 2) MSET 一次请求
redis-cli MSET k1 v1 k2 v2
# 3) Pipeline 批量写入
printf "SET k3 v3\nSET k4 v4\n" | redis-cli --pipe
示例:过期分散,避免过期风暴
# 统一过期 60s(风险:同一时间大量过期)
redis-cli SET cache:1 v1 EX 60
redis-cli SET cache:2 v2 EX 60
# 分散过期:加入随机抖动
redis-cli SET cache:3 v3 EX 60
redis-cli SET cache:4 v4 EX 73
命令解释
- MGET/MSET:减少网络往返
- --pipe:客户端批量提交,降低 RTT
5. 慢查询治理流程(可执行模板)#
治理步骤与命令
# 1) 收集慢日志
redis-cli SLOWLOG GET 128 > /tmp/slowlog.txt
# 2) 关联命令统计
redis-cli INFO commandstats > /tmp/commandstats.txt
# 3) 定位 key 模式(示例:通过慢日志中 key 进行二次核验)
# 手工提取 key 后使用 MEMORY USAGE
redis-cli MEMORY USAGE some:hot:key
# 4) 验证优化结果
redis-cli --latency -h 127.0.0.1 -p 6379
redis-cli INFO stats | egrep 'instantaneous_ops_per_sec|rejected_connections'
6. 现场排查清单(带命令)#
快速检查命令
# 1) 查看阻塞与连接
redis-cli INFO clients | egrep 'blocked_clients|connected_clients'
# 2) 查看慢日志长度
redis-cli SLOWLOG LEN
# 3) 关注危险命令
redis-cli CONFIG GET rename-command
排错步骤示例(场景:延迟突增)
# 步骤1:检查 CPU 和延迟
redis-cli --latency -h 127.0.0.1 -p 6379
# 步骤2:抓取慢日志
redis-cli SLOWLOG GET 20
# 步骤3:定位大 key
redis-cli --bigkeys
# 预期:找出耗时命令、热点 key 或大 key
7. 练习(动手验证)#
1) 设置慢日志阈值为 2ms,执行一个自定义 Lua 脚本,观察 SLOWLOG GET 输出。
2) 使用 SCAN 替代 KEYS 完成同样的匹配任务,并对比阻塞情况。
3) 对一个大 List 进行分页读取,并记录每次 LRANGE 的耗时。