Redis 线上问题排查完整手册
Redis 线上问题排查完整手册
本手册专门针对Redis生产环境故障排查,涵盖内存、性能、连接、数据一致性、集群架构等核心问题,提供详细的中文说明和实战经验总结。
🚨 快速诊断命令集合
Redis线上出现问题时,首先需要获取基本状态信息。以下命令可以快速了解Redis当前运行状况:
# 1. 检查Redis服务是否正常响应
redis-cli ping
# 正常返回:PONG,如果无响应说明服务异常# 2. 获取服务器基本信息(版本、运行时间、配置等)
redis-cli info server# 3. 检查内存使用情况(最重要的监控指标)
redis-cli info memory# 4. 查看操作统计信息(QPS、命令执行次数等)
redis-cli info stats# 5. 检查主从复制状态
redis-cli info replication# 6. 查看持久化相关信息
redis-cli info persistence
📅 一、内存问题深度排查
🔍 问题背景与成因
Redis内存问题是线上最常见的故障类型,主要包括:
- 内存泄漏:程序bug导致内存无法释放
- 大Key问题:单个key占用内存过大,影响性能
- 内存碎片:频繁的内存分配释放导致碎片化
- 过期策略失效:大量过期key未及时清理
- 配置不当:maxmemory设置过高或过期策略不合理
🎯 症状识别与判断
出现以下情况时,应重点排查内存问题:
- 系统层面:Redis进程被OOM Killer杀死,系统内存不足
- 应用层面:响应速度明显变慢,客户端连接超时
- 监控告警:内存使用率持续上升,达到告警阀值
- 业务影响:缓存命中率下降,数据库压力增大
🔧 详细排查步骤
第一步:检查整体内存使用情况
# 获取详细的内存统计信息
redis-cli info memory# 重点关注以下指标:
# used_memory_human: Redis实际使用内存(人类可读格式)
# used_memory_rss_human: 系统分配给Redis的物理内存
# mem_fragmentation_ratio: 内存碎片率(正常范围1.0-1.5)
# used_memory_peak_human: 历史内存使用峰值
# maxmemory_human: 设置的最大内存限制
第二步:识别和分析大Key
# 扫描并统计各数据类型的大key(耗时较长,建议在从库执行)
redis-cli --bigkeys# 手动检查特定key的内存占用(Redis 4.0+)
redis-cli memory usage key_name# 批量检查多个key的内存使用情况
redis-cli --scan --pattern "user:*" | xargs -I {} redis-cli memory usage {}# 分析key的详细结构(了解数据类型和元素数量)
redis-cli debug object key_name
第三步:检查过期key和清理策略
# 查看各数据库的key统计信息
redis-cli info keyspace
# 输出示例:db0:keys=10000,expires=3000,avg_ttl=7200000# 检查特定key的过期时间
redis-cli ttl key_name
# 返回值:-1(永不过期) -2(key不存在) >0(剩余秒数)# 获取当前的过期策略配置
redis-cli config get maxmemory-policy
第四步:分析内存碎片情况
# 获取详细的内存统计(Redis 4.0+)
redis-cli memory stats# 查看内存分配器信息
redis-cli memory malloc-stats
💡 解决方案与优化策略
立即缓解内存压力
# 1. 清理特定模式的过期key(谨慎使用,会阻塞服务)
redis-cli eval "
local keys = redis.call('keys', ARGV[1])
local count = 0
for i=1,#keys doif redis.call('ttl', keys[i]) == -1 thenredis.call('del', keys[i])count = count + 1end
end
return count
" 0 "temp:*"# 2. 手动触发内存碎片整理(Redis 4.0+)
redis-cli memory purge# 3. 设置合理的内存限制和淘汰策略
redis-cli config set maxmemory 4gb
redis-cli config set maxmemory-policy allkeys-lru
长期优化措施
# 1. 启用惰性删除,减少删除大key时的阻塞
redis-cli config set lazyfree-lazy-eviction yes
redis-cli config set lazyfree-lazy-expire yes
redis-cli config set lazyfree-lazy-server-del yes# 2. 调整过期key的清理频率
redis-cli config set hz 100 # 增加后台任务频率# 3. 优化数据结构,减少内存占用
# 例如:将大hash拆分为多个小hash
# 将长字符串压缩存储
⚡ 二、性能问题深度分析
🔍 问题背景与成因
Redis性能问题通常表现为响应延迟增加,主要原因包括:
- 慢查询命令:复杂度高的命令(如keys、sort等)
- 阻塞操作:持久化、主从同步等阻塞主线程
- 网络问题:带宽不足、网络延迟、连接池配置不当
- 系统资源:CPU、内存、磁盘IO成为瓶颈
- 配置问题:不合理的持久化配置、内存淘汰策略等
🎯 性能问题识别
以下现象提示可能存在性能问题:
- 响应延迟:平均响应时间超过正常基线
- 超时增加:客户端频繁出现连接或读取超时
- QPS下降:每秒处理请求数明显降低
- CPU异常:Redis进程CPU使用率异常高或异常低
🔧 性能排查详细步骤
第一步:检查慢查询日志
# 获取最近的慢查询记录(默认显示10条)
redis-cli slowlog get 10# 查看慢查询的配置阀值(微秒为单位)
redis-cli config get slowlog-log-slower-than
# 建议生产环境设置为10000微秒(10毫秒)# 查看慢查询日志的最大长度
redis-cli config get slowlog-max-len# 清空慢查询日志
redis-cli slowlog reset
第二步:分析连接和操作统计
# 查看客户端连接信息
redis-cli info clients
# 重点关注:
# connected_clients: 当前连接数
# client_recent_max_input_buffer: 最大输入缓冲区
# client_recent_max_output_buffer: 最大输出缓冲区# 查看详细的统计信息
redis-cli info stats
# 重点关注:
# total_commands_processed: 总命令执行数
# instantaneous_ops_per_sec: 当前QPS
# total_net_input_bytes: 网络输入字节数
# total_net_output_bytes: 网络输出字节数
第三步:实时监控命令执行
# 实时监控所有执行的命令(生产环境慎用,影响性能)
redis-cli monitor# 监控特定时间段的延迟情况
redis-cli --latency-history
# 每15秒输出一次延迟统计# 监控内在延迟(内部操作延迟)
redis-cli --intrinsic-latency 60
# 运行60秒,检测系统本身的延迟
第四步:检查阻塞操作
# 查看持久化相关信息
redis-cli info persistence
# 重点关注:
# rdb_bgsave_in_progress: 是否正在进行RDB备份
# aof_rewrite_in_progress: 是否正在进行AOF重写# 查看最后一次成功保存的时间
redis-cli lastsave# 查看主从同步延迟(在从库执行)
redis-cli info replication
# 关注master_repl_offset和slave_repl_offset的差值
💡 性能优化解决方案
慢查询优化
# 1. 合理设置慢查询阀值(生产环境建议10ms)
redis-cli config set slowlog-log-slower-than 10000# 2. 增加日志保存数量,便于分析
redis-cli config set slowlog-max-len 1000# 3. 禁用或重命名危险的慢命令
redis-cli config set rename-command-keys "KEYS_DANGEROUS"
redis-cli config set rename-command-flushall "FLUSHALL_DANGEROUS"
持久化优化
# 1. 调整RDB持久化策略(减少频率)
redis-cli config set save "1800 1 600 100 300 1000"
# 含义:1800秒内至少1个key改变,或600秒内100个key改变,或300秒内1000个key改变# 2. 优化AOF配置
redis-cli config set appendonly yes
redis-cli config set appendfsync everysec # 每秒同步一次
redis-cli config set auto-aof-rewrite-percentage 100
redis-cli config set auto-aof-rewrite-min-size 128mb
网络和连接优化
# 1. 启用TCP长连接保活
redis-cli config set tcp-keepalive 300# 2. 调整客户端连接超时
redis-cli config set timeout 0 # 0表示不超时,根据实际情况调整# 3. 限制单个客户端的输出缓冲区大小
redis-cli config set client-output-buffer-limit "normal 0 0 0"
🔌 三、连接问题完全排查指南
🔍 连接问题的常见场景
Redis连接问题在高并发环境下特别常见,主要包括:
- 连接数耗尽:达到maxclients限制,新连接被拒绝
- 连接池配置不当:客户端连接池参数设置不合理
- 网络问题:网络不稳定、防火墙限制、DNS解析问题
- 认证问题:密码错误、权限不足
- 系统资源限制:操作系统的文件描述符限制
🎯 连接问题症状
- 连接拒绝:客户端报"Connection refused"错误
- 连接超时:建立连接时间过长或读取超时
- 连接不稳定:连接频繁断开重连
- 连接池耗尽:应用报连接池获取不到连接
🔧 连接问题排查步骤
第一步:检查当前连接状态
# 查看连接统计信息
redis-cli info clients
# 重点指标说明:
# connected_clients: 当前连接的客户端数量
# client_recent_max_input_buffer: 最近客户端最大输入缓冲区大小
# client_recent_max_output_buffer: 最近客户端最大输出缓冲区大小
# blocked_clients: 被阻塞的客户端数量(通常是BLPOP等阻塞命令)# 获取最大客户端连接数配置
redis-cli config get maxclients
第二步:分析具体的连接详情
# 查看所有客户端连接的详细信息
redis-cli client list
# 输出包含每个连接的:
# - addr: 客户端地址和端口
# - fd: 文件描述符
# - name: 连接名称
# - age: 连接存活时间
# - idle: 空闲时间
# - flags: 连接标志
# - db: 当前数据库
# - sub/psub: 订阅的频道数# 按连接时间排序,查找异常连接
redis-cli client list | sort -k4 -n
第三步:检查网络和系统配置
# 检查Redis网络相关配置
redis-cli config get bind # 绑定的IP地址
redis-cli config get port # 端口号
redis-cli config get protected-mode # 保护模式
redis-cli config get timeout # 客户端超时时间
redis-cli config get tcp-keepalive # TCP保活时间# 在系统层面检查网络连接(需要系统管理员权限)
netstat -tlnp | grep 6379 # 查看Redis端口监听状态
ss -tnlp | grep 6379 # 使用ss命令查看连接状态(推荐)
💡 连接问题解决方案
连接数限制优化
# 1. 增加最大客户端连接数(根据服务器性能调整)
redis-cli config set maxclients 2000# 2. 设置合理的客户端超时时间
redis-cli config set timeout 300 # 5分钟超时# 3. 启用TCP keepalive,及时清理死连接
redis-cli config set tcp-keepalive 300 # 5分钟保活探测
强制清理异常连接
# 1. 根据IP地址杀死特定客户端连接
redis-cli client kill ip 192.168.1.100# 2. 杀死空闲时间超过指定秒数的连接
redis-cli client kill idle 3600 # 杀死空闲1小时以上的连接# 3. 根据连接类型杀死连接
redis-cli client kill type normal # 杀死普通连接
redis-cli client kill type master # 杀死主从复制连接(谨慎使用)# 4. 批量清理异常连接的脚本
redis-cli eval "
local clients = redis.call('client', 'list')
local killed = 0
for client in clients:gmatch('[^\r\n]+') dolocal idle = client:match('idle=(%d+)')if idle and tonumber(idle) > 7200 then -- 空闲超过2小时local addr = client:match('addr=([%d%.]+:%d+)')if addr thenredis.call('client', 'kill', 'addr', addr)killed = killed + 1endend
end
return killed
" 0
系统级优化
# 检查系统文件描述符限制
ulimit -n# 临时增加文件描述符限制(需要root权限)
ulimit -n 65535# 永久修改(编辑 /etc/security/limits.conf)
echo "redis soft nofile 65535" >> /etc/security/limits.conf
echo "redis hard nofile 65535" >> /etc/security/limits.conf
📦 四、数据一致性问题深度诊断
🔍 数据一致性问题类型
数据一致性是Redis集群和主从架构中的核心问题:
- 主从数据不同步:网络延迟、配置错误导致主从数据差异
- 数据意外丢失:持久化配置问题、服务器故障、误操作
- 缓存穿透:大量请求未命中缓存,直接冲击数据库
- 缓存雪崩:大量缓存同时失效,系统压力激增
- 脑裂问题:网络分区导致出现多个主节点
🎯 数据问题识别标准
- 业务层面:数据查询结果不一致,缓存命中率异常低
- 监控指标:主从延迟过大,持久化失败告警
- 系统表现:数据库负载突增,应用响应慢
🔧 数据一致性排查流程
第一步:检查主从复制状态
# 在主库执行,检查主库状态
redis-cli info replication
# 重点关注:
# role:master # 确认当前实例角色
# connected_slaves:1 # 连接的从库数量
# master_repl_offset:12345 # 主库复制偏移量# 在从库执行,检查从库状态
redis-cli info replication
# 重点关注:
# role:slave # 确认从库角色
# master_host:192.168.1.10 # 主库地址
# master_port:6379 # 主库端口
# master_link_status:up # 与主库连接状态
# slave_repl_offset:12340 # 从库复制偏移量
# slave_read_only:1 # 是否只读模式
第二步:检查数据同步延迟
# 计算主从同步延迟
# 主库偏移量 - 从库偏移量 = 延迟的字节数# 在主库写入测试数据
redis-cli set sync_test_$(date +%s) "test_value"# 立即在从库检查是否同步
redis-cli get sync_test_$(date +%s)# 检查复制积压缓冲区配置
redis-cli config get repl-backlog-size
redis-cli config get repl-backlog-ttl
第三步:验证持久化完整性
# 检查持久化状态
redis-cli info persistence
# 重点关注:
# rdb_last_save_time:1609459200 # 最后RDB保存时间
# rdb_last_bgsave_status:ok # 最后备份状态
# aof_enabled:1 # AOF是否启用
# aof_last_write_status:ok # AOF写入状态# 检查持久化文件
redis-cli config get dir # 获取数据目录
redis-cli config get dbfilename # 获取RDB文件名
redis-cli config get appendfilename # 获取AOF文件名# 手动触发持久化测试
redis-cli bgsave # 后台保存RDB
redis-cli bgrewriteaof # 重写AOF文件
第四步:检查key过期和淘汰策略
# 检查内存淘汰策略
redis-cli config get maxmemory-policy
# 常见策略:
# noeviction: 不淘汰,内存满时报错
# allkeys-lru: 所有key中淘汰最近最少使用
# volatile-lru: 有过期时间的key中淘汰LRU
# allkeys-random: 随机淘汰key# 检查key的过期情况
redis-cli ttl important_key # 检查重要key的过期时间
redis-cli pttl important_key # 以毫秒为单位检查过期时间# 统计各数据库的key数量和过期key数量
redis-cli info keyspace
💡 数据一致性修复方案
主从同步问题修复
# 1. 重新建立主从关系(在从库执行)
redis-cli slaveof no one # 取消主从关系
redis-cli flushall # 清空从库数据(谨慎操作)
redis-cli slaveof 192.168.1.10 6379 # 重新设置主库# 2. 调整复制缓冲区大小,减少全量同步概率
redis-cli config set repl-backlog-size 64mb # 增大积压缓冲区
redis-cli config set repl-backlog-ttl 7200 # 延长缓冲区保留时间# 3. 优化网络和同步参数
redis-cli config set repl-timeout 60 # 复制超时时间
redis-cli config set repl-ping-slave-period 10 # 主库ping从库间隔
数据恢复操作
# 1. 从RDB文件恢复数据
redis-cli shutdown nosave # 关闭服务但不保存
# 替换dump.rdb文件到数据目录
redis-server /path/to/redis.conf # 重启服务# 2. 从AOF文件恢复数据
redis-cli config set appendonly yes
redis-cli debug reload # 重新加载持久化数据# 3. 修复损坏的AOF文件
redis-check-aof --fix /path/to/appendonly.aof
防止数据丢失的预防措施
# 1. 同时启用RDB和AOF双重保障
redis-cli config set save "900 1 300 10 60 1000" # RDB策略
redis-cli config set appendonly yes # 启用AOF
redis-cli config set appendfsync everysec # 每秒同步AOF# 2. 配置最小写入成功数量(集群环境)
redis-cli config set min-slaves-to-write 1 # 至少1个从库写入成功
redis-cli config set min-slaves-max-lag 10 # 从库延迟不超过10秒# 3. 设置关键业务数据不过期
redis-cli persist critical_business_key # 移除key的过期时间
🔧 五、集群架构问题排查
🔍 Redis集群常见问题
Redis集群在大规模部署中面临诸多挑战:
- 节点故障:服务器宕机、网络中断导致节点不可用
- 槽位迁移失败:数据重分布过程中的异常
- 脑裂问题:网络分区导致集群分裂
- 选举问题:主节点选举失败或选举时间过长
- 数据倾斜:某些节点数据量过大,负载不均衡
🔧 集群状态检查
集群整体状态诊断
# 1. 检查集群基本信息
redis-cli cluster info
# 重点关注:
# cluster_state:ok # 集群状态是否正常
# cluster_slots_assigned:16384 # 已分配的槽位数量
# cluster_slots_ok:16384 # 正常的槽位数量
# cluster_slots_pfail:0 # 可能故障的槽位
# cluster_slots_fail:0 # 确认故障的槽位
# cluster_known_nodes:6 # 已知节点数量# 2. 查看所有节点信息
redis-cli cluster nodes
# 输出格式:节点ID 地址:端口 角色 主节点ID 连接状态 槽位范围# 3. 检查槽位分配情况
redis-cli cluster slots
# 显示每个槽位范围对应的主从节点信息
节点健康状态检查
# 1. 检查特定节点的连接状态
redis-cli -h 192.168.1.10 -p 7001 ping# 2. 批量检查所有节点状态
for port in 7001 7002 7003 7004 7005 7006; doecho "检查节点 192.168.1.10:$port"redis-cli -h 192.168.1.10 -p $port ping
done# 3. 检查节点间的网络连通性
redis-cli cluster meet 192.168.1.11 7001 # 添加新节点到集群
集群数据一致性验证
# 1. 验证集群数据分布
redis-cli --cluster check 192.168.1.10:7001
# 自动检查集群状态和数据分布# 2. 检查特定key在哪个节点
redis-cli cluster keyslot mykey # 获取key对应的槽位
redis-cli cluster nodes | grep "0-5460" # 查找负责该槽位的节点# 3. 验证集群中的数据一致性
redis-cli --cluster call 192.168.1.10:7001 info replication
# 在所有节点执行相同命令,比较结果
💡 集群问题解决方案
故障节点恢复
# 1. 移除完全故障的节点
redis-cli cluster forget <node-id> # 从集群中移除节点# 2. 重新加入修复后的节点
redis-cli cluster meet <ip> <port> # 重新加入集群
redis-cli cluster replicate <master-node-id> # 设置为从节点# 3. 替换故障的主节点
redis-cli cluster failover # 在从节点执行,强制故障转移
redis-cli cluster failover force # 强制故障转移(即使主节点正常)
槽位重新分配
# 1. 手动迁移槽位(需要redis-cli --cluster)
redis-cli --cluster reshard 192.168.1.10:7001
# 交互式界面,指定迁移的槽位数量和目标节点# 2. 修复槽位分配异常
redis-cli --cluster fix 192.168.1.10:7001
# 自动修复集群中的常见问题# 3. 重新平衡集群
redis-cli --cluster rebalance 192.168.1.10:7001
# 自动调整各节点的槽位分配,使负载更均衡# 4. 手动分配特定槽位
redis-cli cluster addslots {0..1000} # 分配槽位0-1000给当前节点
redis-cli cluster delslots {0..1000} # 从当前节点删除槽位0-1000
集群扩容和缩容
# 集群扩容:添加新节点
# 1. 启动新的Redis节点
redis-server --port 7007 --cluster-enabled yes --cluster-config-file nodes-7007.conf# 2. 将新节点加入集群
redis-cli --cluster add-node 192.168.1.10:7007 192.168.1.10:7001# 3. 为新节点分配槽位
redis-cli --cluster reshard 192.168.1.10:7001# 集群缩容:移除节点
# 1. 迁移节点上的槽位
redis-cli --cluster reshard --cluster-from <node-id> --cluster-to <target-node-id> --cluster-slots 1000 192.168.1.10:7001# 2. 移除空节点
redis-cli --cluster del-node 192.168.1.10:7001 <node-id>
📋 六、专业运维监控脚本
🔍 全方位健康检查脚本
#!/bin/bash
# Redis生产环境健康检查脚本
# 使用方法: ./redis_health_check.sh [redis-host] [redis-port]REDIS_HOST=${1:-127.0.0.1}
REDIS_PORT=${2:-6379}
REDIS_CLI="redis-cli -h $REDIS_HOST -p $REDIS_PORT"echo "========================================"
echo "Redis健康检查报告 - $(date)"
echo "目标服务器: $REDIS_HOST:$REDIS_PORT"
echo "========================================"# 1. 基础连接测试
echo "🔍 1. 基础连接检查"
if $REDIS_CLI ping > /dev/null 2>&1; thenecho "✅ Redis服务正常响应"# 获取基本信息VERSION=$($REDIS_CLI info server | grep redis_version | cut -d: -f2 | tr -d '\r')UPTIME=$($REDIS_CLI info server | grep uptime_in_seconds | cut -d: -f2 | tr -d '\r')echo " 版本: $VERSION"echo " 运行时间: $((UPTIME/86400))天 $((UPTIME%86400/3600))小时"
elseecho "❌ Redis服务无响应,请检查服务状态和网络连接"exit 1
fi# 2. 内存使用情况
echo -e "\n🧠 2. 内存使用分析"
USED_MEMORY=$($REDIS_CLI info memory | grep "used_memory_human" | head -1 | cut -d: -f2 | tr -d '\r')
RSS_MEMORY=$($REDIS_CLI info memory | grep "used_memory_rss_human" | cut -d: -f2 | tr -d '\r')
FRAG_RATIO=$($REDIS_CLI info memory | grep "mem_fragmentation_ratio" | cut -d: -f2 | tr -d '\r')
MAX_MEMORY=$($REDIS_CLI config get maxmemory | tail -1)echo " 使用内存: $USED_MEMORY"
echo " 物理内存: $RSS_MEMORY"
echo " 碎片率: $FRAG_RATIO"
echo " 内存限制: $(if [ "$MAX_MEMORY" = "0" ]; then echo "无限制"; else echo "${MAX_MEMORY}字节"; fi)"# 判断内存状况
if (( $(echo "$FRAG_RATIO > 2.0" | bc -l) )); thenecho "⚠️ 警告: 内存碎片率过高($FRAG_RATIO),建议进行内存整理"
fi# 3. 连接状态检查
echo -e "\n🔗 3. 连接状态分析"
CONNECTED_CLIENTS=$($REDIS_CLI info clients | grep "connected_clients" | cut -d: -f2 | tr -d '\r')
MAX_CLIENTS=$($REDIS_CLI config get maxclients | tail -1)
BLOCKED_CLIENTS=$($REDIS_CLI info clients | grep "blocked_clients" | cut -d: -f2 | tr -d '\r')echo " 当前连接数: $CONNECTED_CLIENTS"
echo " 最大连接数: $MAX_CLIENTS"
echo " 阻塞连接数: $BLOCKED_CLIENTS"# 连接数使用率检查
CONNECTION_USAGE=$((CONNECTED_CLIENTS * 100 / MAX_CLIENTS))
if [ $CONNECTION_USAGE -gt 80 ]; thenecho "⚠️ 警告: 连接数使用率 ${CONNECTION_USAGE}%,接近上限"
fi# 4. 性能指标检查
echo -e "\n⚡ 4. 性能指标分析"
OPS_PER_SEC=$($REDIS_CLI info stats | grep "instantaneous_ops_per_sec" | cut -d: -f2 | tr -d '\r')
TOTAL_COMMANDS=$($REDIS_CLI info stats | grep "total_commands_processed" | cut -d: -f2 | tr -d '\r')
SLOWLOG_LEN=$($REDIS_CLI slowlog len)echo " 当前QPS: $OPS_PER_SEC"
echo " 总命令数: $TOTAL_COMMANDS"
echo " 慢查询数: $SLOWLOG_LEN"if [ $SLOWLOG_LEN -gt 100 ]; thenecho "⚠️ 警告: 慢查询数量较多($SLOWLOG_LEN),建议检查慢查询日志"echo " 最近3条慢查询:"$REDIS_CLI slowlog get 3 | grep -E "^\d+\)" -A 3
fi# 5. 持久化状态
echo -e "\n💾 5. 持久化状态检查"
RDB_LAST_SAVE=$($REDIS_CLI info persistence | grep "rdb_last_save_time" | cut -d: -f2 | tr -d '\r')
AOF_ENABLED=$($REDIS_CLI info persistence | grep "aof_enabled" | cut -d: -f2 | tr -d '\r')
RDB_STATUS=$($REDIS_CLI info persistence | grep "rdb_last_bgsave_status" | cut -d: -f2 | tr -d '\r')CURRENT_TIME=$(date +%s)
LAST_SAVE_AGO=$((CURRENT_TIME - RDB_LAST_SAVE))echo " RDB状态: $RDB_STATUS"
echo " 上次保存: $((LAST_SAVE_AGO/3600))小时前"
echo " AOF启用: $(if [ "$AOF_ENABLED" = "1" ]; then echo "是"; else echo "否"; fi)"if [ $LAST_SAVE_AGO -gt 21600 ]; then # 6小时echo "⚠️ 警告: RDB备份时间过久,建议检查持久化配置"
fi# 6. 主从复制状态(如果适用)
echo -e "\n🔄 6. 主从复制检查"
ROLE=$($REDIS_CLI info replication | grep "role" | cut -d: -f2 | tr -d '\r')
echo " 当前角色: $ROLE"if [ "$ROLE" = "master" ]; thenCONNECTED_SLAVES=$($REDIS_CLI info replication | grep "connected_slaves" | cut -d: -f2 | tr -d '\r')echo " 连接的从库: $CONNECTED_SLAVES"
elif [ "$ROLE" = "slave" ]; thenMASTER_LINK_STATUS=$($REDIS_CLI info replication | grep "master_link_status" | cut -d: -f2 | tr -d '\r')MASTER_LAST_IO=$($REDIS_CLI info replication | grep "master_last_io_seconds_ago" | cut -d: -f2 | tr -d '\r')echo " 主库连接状态: $MASTER_LINK_STATUS"echo " 上次同步: ${MASTER_LAST_IO}秒前"if [ "$MASTER_LINK_STATUS" != "up" ]; thenecho "❌ 错误: 与主库连接异常"fi
fi# 7. 集群状态检查(如果启用)
if $REDIS_CLI cluster info > /dev/null 2>&1; thenecho -e "\n🔧 7. 集群状态检查"CLUSTER_STATE=$($REDIS_CLI cluster info | grep "cluster_state" | cut -d: -f2 | tr -d '\r')CLUSTER_NODES=$($REDIS_CLI cluster info | grep "cluster_known_nodes" | cut -d: -f2 | tr -d '\r')echo " 集群状态: $CLUSTER_STATE"echo " 节点数量: $CLUSTER_NODES"if [ "$CLUSTER_STATE" != "ok" ]; thenecho "❌ 错误: 集群状态异常"fi
fi# 8. 总结建议
echo -e "\n📋 8. 健康检查总结"
echo "✅ 基础功能: 正常"
echo "$(if (( $(echo "$FRAG_RATIO > 2.0" | bc -l) )); then echo "⚠️ 内存碎片: 需要关注"; else echo "✅ 内存状态: 良好"; fi)"
echo "$(if [ $CONNECTION_USAGE -gt 80 ]; then echo "⚠️ 连接使用: 需要关注"; else echo "✅ 连接状态: 正常"; fi)"
echo "$(if [ $SLOWLOG_LEN -gt 100 ]; then echo "⚠️ 性能状态: 需要优化"; else echo "✅ 性能状态: 良好"; fi)"
echo "$(if [ $LAST_SAVE_AGO -gt 21600 ]; then echo "⚠️ 持久化: 需要检查"; else echo "✅ 持久化: 正常"; fi)"echo -e "\n========================================"
echo "检查完成时间: $(date)"
echo "========================================"
🚨 性能监控脚本
#!/bin/bash
# Redis性能实时监控脚本
# 使用方法: ./redis_performance_monitor.sh [interval]REDIS_CLI="redis-cli"
INTERVAL=${1:-5} # 监控间隔,默认5秒echo "Redis性能监控 - 间隔${INTERVAL}秒,按Ctrl+C停止"
echo "时间 QPS 连接数 内存使用 慢查询 延迟(ms) 键空间"
echo "=============================================================="while true; doTIMESTAMP=$(date +"%H:%M:%S")# 获取QPSQPS=$($REDIS_CLI info stats | grep instantaneous_ops_per_sec | cut -d: -f2 | tr -d '\r')# 获取连接数CLIENTS=$($REDIS_CLI info clients | grep connected_clients | cut -d: -f2 | tr -d '\r')# 获取内存使用MEMORY=$($REDIS_CLI info memory | grep used_memory_human | head -1 | cut -d: -f2 | tr -d '\r')# 获取慢查询数量SLOWLOG=$($REDIS_CLI slowlog len)# 测试延迟(简化版本)START_TIME=$(date +%s%N)$REDIS_CLI ping > /dev/nullEND_TIME=$(date +%s%N)LATENCY=$(((END_TIME - START_TIME) / 1000000))# 获取键空间信息KEYSPACE=$($REDIS_CLI info keyspace | grep "db0:" | cut -d: -f2 | cut -d, -f1 | cut -d= -f2)KEYSPACE=${KEYSPACE:-0}printf "%-8s %6s %8s %10s %8s %8s %8s\n" "$TIMESTAMP" "$QPS" "$CLIENTS" "$MEMORY" "$SLOWLOG" "$LATENCY" "$KEYSPACE"sleep $INTERVAL
done
📊 集群监控脚本
#!/bin/bash
# Redis集群状态监控脚本
# 使用方法: ./redis_cluster_monitor.sh <cluster-node-ip:port>CLUSTER_NODE=${1:-127.0.0.1:7001}
REDIS_CLI="redis-cli -c -h $(echo $CLUSTER_NODE | cut -d: -f1) -p $(echo $CLUSTER_NODE | cut -d: -f2)"echo "Redis集群监控 - 节点: $CLUSTER_NODE"
echo "========================================"# 检查集群基本状态
echo "🔧 集群基本状态:"
CLUSTER_STATE=$($REDIS_CLI cluster info | grep cluster_state | cut -d: -f2)
CLUSTER_NODES_COUNT=$($REDIS_CLI cluster info | grep cluster_known_nodes | cut -d: -f2)
CLUSTER_SIZE=$($REDIS_CLI cluster info | grep cluster_size | cut -d: -f2)echo " 集群状态: $CLUSTER_STATE"
echo " 节点总数: $CLUSTER_NODES_COUNT"
echo " 集群大小: $CLUSTER_SIZE"# 检查各节点状态
echo -e "\n📊 节点详细状态:"
echo "节点ID 地址:端口 角色 状态 槽位数量"
echo "================================================================================="$REDIS_CLI cluster nodes | while read line; doNODE_ID=$(echo $line | awk '{print $1}' | head -c 8)ADDRESS=$(echo $line | awk '{print $2}')FLAGS=$(echo $line | awk '{print $3}')SLOTS=$(echo $line | grep -o '\[.*\]' | wc -l)# 解析角色if [[ $FLAGS == *"master"* ]]; thenROLE="主节点"elif [[ $FLAGS == *"slave"* ]]; thenROLE="从节点"elseROLE="未知"fi# 解析状态if [[ $FLAGS == *"fail"* ]]; thenSTATUS="故障"elif [[ $FLAGS == *"handshake"* ]]; thenSTATUS="握手中"elseSTATUS="正常"fiprintf "%-8s... %-18s %-8s %-8s %8s\n" "$NODE_ID" "$ADDRESS" "$ROLE" "$STATUS" "$SLOTS"
done# 检查槽位分配
echo -e "\n🎯 槽位分配统计:"
ASSIGNED_SLOTS=$($REDIS_CLI cluster info | grep cluster_slots_assigned | cut -d: -f2)
OK_SLOTS=$($REDIS_CLI cluster info | grep cluster_slots_ok | cut -d: -f2)
FAIL_SLOTS=$($REDIS_CLI cluster info | grep cluster_slots_fail | cut -d: -f2)echo " 已分配槽位: $ASSIGNED_SLOTS / 16384"
echo " 正常槽位: $OK_SLOTS"
echo " 故障槽位: $FAIL_SLOTS"if [ "$FAIL_SLOTS" -gt 0 ]; thenecho "⚠️ 警告: 存在故障槽位,需要立即处理"
fi# 检查各节点性能
echo -e "\n⚡ 节点性能统计:"
echo "地址:端口 内存使用 QPS 连接数 角色"
echo "=================================================="$REDIS_CLI cluster nodes | grep -v fail | while read line; doADDRESS=$(echo $line | awk '{print $2}' | cut -d@ -f1)HOST=$(echo $ADDRESS | cut -d: -f1)PORT=$(echo $ADDRESS | cut -d: -f2)FLAGS=$(echo $line | awk '{print $3}')if [[ $FLAGS == *"master"* ]]; thenROLE="主节点"elseROLE="从节点"fi# 获取节点性能数据MEMORY=$(redis-cli -h $HOST -p $PORT info memory 2>/dev/null | grep used_memory_human | head -1 | cut -d: -f2 | tr -d '\r')QPS=$(redis-cli -h $HOST -p $PORT info stats 2>/dev/null | grep instantaneous_ops_per_sec | cut -d: -f2 | tr -d '\r')CLIENTS=$(redis-cli -h $HOST -p $PORT info clients 2>/dev/null | grep connected_clients | cut -d: -f2 | tr -d '\r')if [ -n "$MEMORY" ]; thenprintf "%-18s %-10s %6s %8s %s\n" "$ADDRESS" "$MEMORY" "$QPS" "$CLIENTS" "$ROLE"elseprintf "%-18s %-10s %6s %8s %s (连接失败)\n" "$ADDRESS" "N/A" "N/A" "N/A" "$ROLE"fi
doneecho -e "\n========================================"
echo "监控完成时间: $(date)"
🆘 七、紧急故障处理手册
🚨 Redis完全无响应处理流程
当Redis完全无法响应时,按以下步骤排查:
#!/bin/bash
# Redis紧急故障处理脚本echo "🆘 Redis紧急故障处理开始..."# 第一步:确认进程状态
echo "🔍 第一步:检查Redis进程状态"
REDIS_PID=$(pgrep -f redis-server)if [ -n "$REDIS_PID" ]; thenecho "✅ Redis进程存在 (PID: $REDIS_PID)"# 检查进程资源使用echo " CPU使用率: $(ps -p $REDIS_PID -o %cpu --no-headers)%"echo " 内存使用: $(ps -p $REDIS_PID -o %mem --no-headers)%"echo " 进程状态: $(ps -p $REDIS_PID -o stat --no-headers)"# 检查文件描述符使用FD_COUNT=$(ls -la /proc/$REDIS_PID/fd 2>/dev/null | wc -l)echo " 打开的文件描述符: $FD_COUNT"elseecho "❌ Redis进程不存在,可能已崩溃"# 检查最近的系统日志echo "📋 检查系统日志中的Redis相关信息:"journalctl -u redis --since "1 hour ago" --no-pager | tail -20
fi# 第二步:检查网络端口
echo -e "\n🔍 第二步:检查网络端口状态"
PORT_STATUS=$(ss -tlnp | grep :6379)
if [ -n "$PORT_STATUS" ]; thenecho "✅ Redis端口6379正在监听"echo " 详细信息: $PORT_STATUS"
elseecho "❌ Redis端口6379未监听"
fi# 第三步:尝试连接测试
echo -e "\n🔍 第三步:连接测试"
PING_RESULT=$(timeout 10 redis-cli ping 2>&1)
if [ "$PING_RESULT" = "PONG" ]; thenecho "✅ Redis响应正常"
elseecho "❌ Redis连接失败: $PING_RESULT"# 尝试使用不同方式连接echo " 尝试TCP连接测试..."if timeout 5 bash -c "</dev/tcp/127.0.0.1/6379"; thenecho " ✅ TCP端口可达,可能是Redis协议问题"elseecho " ❌ TCP端口不可达,Redis服务异常"fi
fi# 第四步:检查系统资源
echo -e "\n🔍 第四步:检查系统资源"
echo " 内存使用情况:"
free -h | head -2echo " 磁盘使用情况:"
df -h | grep -E "(/$|/var|/tmp)"echo " 系统负载:"
uptime# 第五步:检查Redis日志
echo -e "\n🔍 第五步:检查Redis日志"
REDIS_LOG="/var/log/redis/redis-server.log"
if [ -f "$REDIS_LOG" ]; thenecho " 最近的Redis日志:"tail -20 "$REDIS_LOG"
elseecho " 未找到标准Redis日志文件,检查其他可能位置..."find /var/log -name "*redis*" -type f 2>/dev/null | head -5
fi# 第六步:生成诊断报告
echo -e "\n📊 第六步:生成诊断总结"
echo "=========================================="
echo "Redis故障诊断报告 - $(date)"
echo "=========================================="if [ -n "$REDIS_PID" ]; thenif [ "$PING_RESULT" = "PONG" ]; thenecho "🟢 状态: Redis运行正常"echo "🔧 建议: 检查应用层面的连接配置"elseecho "🟡 状态: Redis进程存在但无响应"echo "🔧 建议: 检查Redis配置、系统资源、网络设置"fi
elseecho "🔴 状态: Redis进程不存在"echo "🔧 建议: 重启Redis服务,检查配置文件"
fiecho -e "\n💡 下一步建议操作:"
if [ -z "$REDIS_PID" ]; thenecho "1. systemctl start redis-server"echo "2. 检查Redis配置文件语法"echo "3. 查看详细的系统日志"
elif [ "$PING_RESULT" != "PONG" ]; thenecho "1. 检查Redis内存使用是否超限"echo "2. 检查是否有长时间运行的慢查询"echo "3. 考虑重启Redis服务"
fiecho "=========================================="
⚡ 内存溢出紧急处理
#!/bin/bash
# Redis内存溢出紧急处理脚本echo "⚠️ Redis内存溢出紧急处理开始..."# 检查当前内存状态
echo "🔍 检查当前内存状态:"
USED_MEMORY=$(redis-cli info memory | grep "used_memory:" | cut -d: -f2 | tr -d '\r')
MAX_MEMORY=$(redis-cli config get maxmemory | tail -1)
FRAG_RATIO=$(redis-cli info memory | grep "mem_fragmentation_ratio" | cut -d: -f2 | tr -d '\r')echo " 当前内存使用: $((USED_MEMORY / 1024 / 1024))MB"
echo " 内存限制: $(if [ "$MAX_MEMORY" = "0" ]; then echo "无限制"; else echo "$((MAX_MEMORY / 1024 / 1024))MB"; fi)"
echo " 内存碎片率: $FRAG_RATIO"# 1. 立即设置内存限制和淘汰策略
echo -e "\n🔧 1. 设置紧急内存保护措施..."
if [ "$MAX_MEMORY" = "0" ]; then# 如果没有设置内存限制,设置为当前使用量的120%NEW_LIMIT=$((USED_MEMORY * 120 / 100))echo " 设置内存限制为: $((NEW_LIMIT / 1024 / 1024))MB"redis-cli config set maxmemory $NEW_LIMIT
fi# 设置激进的淘汰策略
redis-cli config set maxmemory-policy allkeys-lru
echo " ✅ 已设置LRU淘汰策略"# 2. 清理过期键
echo -e "\n🗑️ 2. 清理过期键..."
EXPIRED_CLEANED=$(redis-cli eval "
local cursor = 0
local count = 0
repeatlocal result = redis.call('SCAN', cursor, 'COUNT', 1000)cursor = tonumber(result[1])local keys = result[2]for i=1, #keys doif redis.call('TTL', keys[i]) == -2 thenredis.call('DEL', keys[i])count = count + 1endend
until cursor == 0
return count
" 0)
echo " ✅ 清理了 $EXPIRED_CLEANED 个过期键"# 3. 清理临时数据(根据业务模式调整)
echo -e "\n🧹 3. 清理临时数据..."
TEMP_PATTERNS=("temp:*" "cache:*" "session:*" "tmp:*")for pattern in "${TEMP_PATTERNS[@]}"; doTEMP_CLEANED=$(redis-cli eval "local keys = redis.call('KEYS', ARGV[1])local count = 0for i=1,#keys do-- 只删除有TTL或者已过期的临时数据local ttl = redis.call('TTL', keys[i])if ttl > 0 and ttl < 3600 then -- 1小时内过期的redis.call('DEL', keys[i])count = count + 1endendreturn count" 0 "$pattern")if [ "$TEMP_CLEANED" -gt 0 ]; thenecho " ✅ 清理了 $TEMP_CLEANED 个临时键 (模式: $pattern)"fi
done# 4. 内存碎片整理
echo -e "\n🔧 4. 内存碎片整理..."
REDIS_VERSION=$(redis-cli info server | grep redis_version | cut -d: -f2 | tr -d '\r')
if [[ $REDIS_VERSION == 4.* ]] || [[ $REDIS_VERSION == 5.* ]] || [[ $REDIS_VERSION == 6.* ]]; thenredis-cli memory purgeecho " ✅ 已触发内存碎片整理"
elseecho " ⚠️ 当前Redis版本不支持内存碎片整理命令"
fi# 5. 检查大键
echo -e "\n🔍 5. 检查大键情况..."
echo " 正在扫描大键(可能需要一些时间)..."
redis-cli --bigkeys | head -20# 6. 最终状态检查
echo -e "\n📊 6. 处理后状态检查..."
NEW_USED_MEMORY=$(redis-cli info memory | grep "used_memory:" | cut -d: -f2 | tr -d '\r')
NEW_FRAG_RATIO=$(redis-cli info memory | grep "mem_fragmentation_ratio" | cut -d: -f2 | tr -d '\r')echo " 处理前内存: $((USED_MEMORY / 1024 / 1024))MB"
echo " 处理后内存: $((NEW_USED_MEMORY / 1024 / 1024))MB"
echo " 节省内存: $(((USED_MEMORY - NEW_USED_MEMORY) / 1024 / 1024))MB"
echo " 新碎片率: $NEW_FRAG_RATIO"# 7. 生成处理报告
echo -e "\n📋 7. 紧急处理总结报告"
echo "=========================================="
echo "Redis内存溢出处理报告 - $(date)"
echo "=========================================="
echo "处理措施:"
echo "✅ 设置内存限制和LRU淘汰策略"
echo "✅ 清理过期键: $EXPIRED_CLEANED 个"
echo "✅ 清理临时数据"
echo "✅ 执行内存碎片整理"
echo ""
echo "内存变化:"
echo " 处理前: $((USED_MEMORY / 1024 / 1024))MB"
echo " 处理后: $((NEW_USED_MEMORY / 1024 / 1024))MB"
echo " 节省: $(((USED_MEMORY - NEW_USED_MEMORY) / 1024 / 1024))MB"
echo ""
echo "后续建议:"
echo "1. 持续监控内存使用情况"
echo "2. 检查应用代码,优化数据存储结构"
echo "3. 考虑增加服务器内存或启用集群"
echo "4. 设置更合理的过期时间策略"
echo "=========================================="
🔄 主从同步断开紧急修复
#!/bin/bash
# Redis主从同步断开紧急修复脚本echo "🔄 Redis主从同步紧急修复开始..."# 检查当前角色
ROLE=$(redis-cli info replication | grep "role:" | cut -d: -f2 | tr -d '\r')
echo "📋 当前节点角色: $ROLE"if [ "$ROLE" = "slave" ]; thenecho -e "\n🔧 执行从库修复流程..."# 获取主库信息MASTER_HOST=$(redis-cli info replication | grep "master_host:" | cut -d: -f2 | tr -d '\r')MASTER_PORT=$(redis-cli info replication | grep "master_port:" | cut -d: -f2 | tr -d '\r')MASTER_LINK_STATUS=$(redis-cli info replication | grep "master_link_status:" | cut -d: -f2 | tr -d '\r')MASTER_LAST_IO=$(redis-cli info replication | grep "master_last_io_seconds_ago:" | cut -d: -f2 | tr -d '\r')echo " 主库地址: $MASTER_HOST:$MASTER_PORT"echo " 连接状态: $MASTER_LINK_STATUS"echo " 上次IO: ${MASTER_LAST_IO}秒前"# 测试主库连通性echo -e "\n🔍 测试主库连通性..."if timeout 5 redis-cli -h $MASTER_HOST -p $MASTER_PORT ping; thenecho "✅ 主库网络连通正常"# 检查主库状态MASTER_ROLE=$(redis-cli -h $MASTER_HOST -p $MASTER_PORT info replication | grep "role:" | cut -d: -f2 | tr -d '\r')if [ "$MASTER_ROLE" = "master" ]; thenecho "✅ 主库角色正常"# 重新建立主从关系echo -e "\n🔄 重新建立主从关系..."echo " 1. 断开当前主从关系..."redis-cli slaveof no onesleep 2echo " 2. 重新连接主库..."redis-cli slaveof $MASTER_HOST $MASTER_PORT echo " 3. 等待同步开始..."sleep 5# 检查同步状态NEW_LINK_STATUS=$(redis-cli info replication | grep "master_link_status:" | cut -d: -f2 | tr -d '\r')echo " 新的同步状态: $NEW_LINK_STATUS"if [ "$NEW_LINK_STATUS" = "up" ]; thenecho "✅ 主从同步已恢复"# 检查同步进度MASTER_OFFSET=$(redis-cli -h $MASTER_HOST -p $MASTER_PORT info replication | grep "master_repl_offset:" | cut -d: -f2 | tr -d '\r')SLAVE_OFFSET=$(redis-cli info replication | grep "slave_repl_offset:" | cut -d: -f2 | tr -d '\r')OFFSET_DIFF=$((MASTER_OFFSET - SLAVE_OFFSET))echo " 主库偏移量: $MASTER_OFFSET"echo " 从库偏移量: $SLAVE_OFFSET"echo " 同步差距: $OFFSET_DIFF 字节"elseecho "❌ 主从同步恢复失败,需要进一步排查"fielseecho "❌ 主库角色异常 ($MASTER_ROLE),可能发生了主从切换"fielseecho "❌ 主库网络不通,需要检查:"echo " 1. 网络连接是否正常"echo " 2. 主库服务是否运行"echo " 3. 防火墙设置是否正确"fielif [ "$ROLE" = "master" ]; thenecho -e "\n🔧 执行主库检查流程..."# 检查从库连接状态CONNECTED_SLAVES=$(redis-cli info replication | grep "connected_slaves:" | cut -d: -f2 | tr -d '\r')echo " 连接的从库数量: $CONNECTED_SLAVES"if [ "$CONNECTED_SLAVES" -gt 0 ]; thenecho " 从库连接详情:"redis-cli info replication | grep -E "slave[0-9]+" | while read line; doecho " $line"doneelseecho "⚠️ 警告: 没有从库连接"# 检查是否有配置文件中的从库信息需要重新连接echo " 建议检查:"echo " 1. 从库服务状态"echo " 2. 网络连接"echo " 3. 从库配置"fielseecho "❌ 未知的Redis角色: $ROLE"
fi# 生成修复报告
echo -e "\n📋 主从同步修复报告"
echo "=========================================="
echo "主从同步修复报告 - $(date)"
echo "=========================================="FINAL_ROLE=$(redis-cli info replication | grep "role:" | cut -d: -f2 | tr -d '\r')
if [ "$FINAL_ROLE" = "slave" ]; thenFINAL_LINK_STATUS=$(redis-cli info replication | grep "master_link_status:" | cut -d: -f2 | tr -d '\r')FINAL_LAST_IO=$(redis-cli info replication | grep "master_last_io_seconds_ago:" | cut -d: -f2 | tr -d '\r')echo "节点角色: 从库"echo "连接状态: $FINAL_LINK_STATUS"echo "最后IO: ${FINAL_LAST_IO}秒前"if [ "$FINAL_LINK_STATUS" = "up" ]; thenecho "✅ 修复状态: 成功"elseecho "❌ 修复状态: 失败"fi
elseFINAL_SLAVES=$(redis-cli info replication | grep "connected_slaves:" | cut -d: -f2 | tr -d '\r')echo "节点角色: 主库"echo "连接从库: $FINAL_SLAVES"
fiecho "=========================================="
📝 八、生产环境配置优化模板
🔧 高性能生产配置
#!/bin/bash
# Redis生产环境配置优化脚本echo "🔧 Redis生产环境配置优化开始..."# 1. 内存管理优化
echo "1. 内存管理配置..."
redis-cli config set maxmemory 8gb # 根据服务器内存调整
redis-cli config set maxmemory-policy allkeys-lru
redis-cli config set maxmemory-samples 10 # 提高LRU准确性# 启用惰性删除,减少删除大key时的阻塞
redis-cli config set lazyfree-lazy-eviction yes
redis-cli config set lazyfree-lazy-expire yes
redis-cli config set lazyfree-lazy-server-del yes
redis-cli config set replica-lazy-flush yes# 2. 网络连接优化
echo "2. 网络连接配置..."
redis-cli config set maxclients 10000 # 根据需求调整
redis-cli config set timeout 300 # 5分钟客户端超时
redis-cli config set tcp-keepalive 300 # TCP保活时间
redis-cli config set tcp-backlog 511 # TCP监听队列长度# 客户端输出缓冲区限制
redis-cli config set client-output-buffer-limit "normal 0 0 0"
redis-cli config set client-output-buffer-limit "replica 256mb 64mb 60"
redis-cli config set client-output-buffer-limit "pubsub 32mb 8mb 60"# 3. 持久化优化
echo "3. 持久化配置..."
# RDB配置 - 适中的频率,避免过于频繁
redis-cli config set save "1800 1 600 100 300 1000"# AOF配置
redis-cli config set appendonly yes
redis-cli config set appendfsync everysec # 性能和安全的平衡
redis-cli config set no-appendfsync-on-rewrite no
redis-cli config set auto-aof-rewrite-percentage 100
redis-cli config set auto-aof-rewrite-min-size 128mb# 4. 主从复制优化
echo "4. 主从复制配置..."
redis-cli config set repl-backlog-size 128mb # 增大复制缓冲区
redis-cli config set repl-backlog-ttl 7200 # 2小时缓冲区保留
redis-cli config set repl-timeout 60 # 复制超时时间
redis-cli config set repl-ping-slave-period 10 # ping从库间隔# 从库配置
redis-cli config set slave-read-only yes # 从库只读
redis-cli config set slave-serve-stale-data yes # 连接断开时提供旧数据# 5. 性能优化
echo "5. 性能优化配置..."
redis-cli config set hash-max-ziplist-entries 512
redis-cli config set hash-max-ziplist-value 64
redis-cli config set list-max-ziplist-size -2
redis-cli config set list-compress-depth 0
redis-cli config set set-max-intset-entries 512
redis-cli config set zset-max-ziplist-entries 128
redis-cli config set zset-max-ziplist-value 64# 6. 安全配置
echo "6. 安全配置..."
redis-cli config set protected-mode yes
redis-cli config set bind "127.0.0.1 10.0.0.100" # 根据实际IP调整
# redis-cli config set requirepass "your_strong_password" # 取消注释并设置密码# 重命名危险命令
redis-cli config set rename-command-flushdb "FLUSHDB_DANGEROUS_COMMAND"
redis-cli config set rename-command-flushall "FLUSHALL_DANGEROUS_COMMAND"
redis-cli config set rename-command-keys "KEYS_DANGEROUS_COMMAND"
redis-cli config set rename-command-config "CONFIG_DANGEROUS_COMMAND"# 7. 慢查询优化
echo "7. 慢查询配置..."
redis-cli config set slowlog-log-slower-than 10000 # 10ms
redis-cli config set slowlog-max-len 1000# 8. 其他优化
echo "8. 其他优化配置..."
redis-cli config set databases 16 # 数据库数量
redis-cli config set hz 100 # 后台任务频率
redis-cli config set dynamic-hz yes # 动态调整hzecho "✅ 配置优化完成!"# 保存配置到文件
echo "💾 保存配置到磁盘..."
redis-cli config rewrite# 输出当前关键配置
echo -e "\n📋 当前关键配置总结:"
echo "内存限制: $(redis-cli config get maxmemory | tail -1)"
echo "最大连接: $(redis-cli config get maxclients | tail -1)"
echo "持久化: RDB+AOF"
echo "淘汰策略: $(redis-cli config get maxmemory-policy | tail -1)"
echo "慢查询阈值: $(redis-cli config get slowlog-log-slower-than | tail -1)微秒"
🛡️ 高可用集群配置
#!/bin/bash
# Redis高可用集群配置脚本echo "🛡️ Redis高可用集群配置开始..."# 集群基本配置
CLUSTER_NODES=("192.168.1.10:7001""192.168.1.10:7002" "192.168.1.10:7003""192.168.1.11:7001""192.168.1.11:7002""192.168.1.11:7003"
)# 1. 集群基础配置
echo "1. 集群基础配置..."
for node in "${CLUSTER_NODES[@]}"; doHOST=$(echo $node | cut -d: -f1)PORT=$(echo $node | cut -d: -f2)echo "配置节点: $node"# 集群必要配置redis-cli -h $HOST -p $PORT config set cluster-enabled yesredis-cli -h $HOST -p $PORT config set cluster-config-file "nodes-${PORT}.conf"redis-cli -h $HOST -p $PORT config set cluster-node-timeout 15000redis-cli -h $HOST -p $PORT config set cluster-announce-ip $HOSTredis-cli -h $HOST -p $PORT config set cluster-announce-port $PORTredis-cli -h $HOST -p $PORT config set cluster-announce-bus-port $((PORT + 10000))# 故障检测和恢复redis-cli -h $HOST -p $PORT config set cluster-require-full-coverage noredis-cli -h $HOST -p $PORT config set cluster-slave-validity-factor 10redis-cli -h $HOST -p $PORT config set cluster-migration-barrier 1
done# 2. 数据安全配置
echo "2. 数据安全配置..."
for node in "${CLUSTER_NODES[@]}"; doHOST=$(echo $node | cut -d: -f1)PORT=$(echo $node | cut -d: -f2)# 最小写入确认redis-cli -h $HOST -p $PORT config set min-replicas-to-write 1redis-cli -h $HOST -p $PORT config set min-replicas-max-lag 10# 持久化配置redis-cli -h $HOST -p $PORT config set save "1800 1 600 100 300 1000"redis-cli -h $HOST -p $PORT config set appendonly yesredis-cli -h $HOST -p $PORT config set appendfsync everysec
done# 3. 性能优化配置
echo "3. 性能优化配置..."
for node in "${CLUSTER_NODES[@]}"; doHOST=$(echo $node | cut -d: -f1)PORT=$(echo $node | cut -d: -f2)# 内存配置redis-cli -h $HOST -p $PORT config set maxmemory 4gbredis-cli -h $HOST -p $PORT config set maxmemory-policy allkeys-lru# 网络配置redis-cli -h $HOST -p $PORT config set tcp-keepalive 300redis-cli -h $HOST -p $PORT config set timeout 300# 客户端配置redis-cli -h $HOST -p $PORT config set maxclients 5000
done# 4. 初始化集群(如果尚未初始化)
echo "4. 检查集群状态..."
FIRST_NODE=${CLUSTER_NODES[0]}
CLUSTER_STATE=$(redis-cli -h $(echo $FIRST_NODE | cut -d: -f1) -p $(echo $FIRST_NODE | cut -d: -f2) cluster info 2>/dev/null | grep cluster_state | cut -d: -f2)if [ "$CLUSTER_STATE" != "ok" ]; thenecho "初始化Redis集群..."NODE_LIST=$(printf "%s " "${CLUSTER_NODES[@]}")redis-cli --cluster create $NODE_LIST --cluster-replicas 1 --cluster-yes
elseecho "✅ 集群已经初始化"
fi# 5. 验证集群配置
echo "5. 验证集群配置..."
for node in "${CLUSTER_NODES[@]}"; doHOST=$(echo $node | cut -d: -f1)PORT=$(echo $node | cut -d: -f2)echo "验证节点: $node"# 检查节点状态PING_RESULT=$(redis-cli -h $HOST -p $PORT ping 2>/dev/null)if [ "$PING_RESULT" = "PONG" ]; thenROLE=$(redis-cli -h $HOST -p $PORT cluster nodes | grep myself | grep -o 'master\|slave')echo " ✅ 节点响应正常 (角色: $ROLE)"elseecho " ❌ 节点无响应"fi
done# 6. 生成集群状态报告
echo -e "\n📊 集群状态报告:"
echo "=================================="
FIRST_HOST=$(echo ${CLUSTER_NODES[0]} | cut -d: -f1)
FIRST_PORT=$(echo ${CLUSTER_NODES[0]} | cut -d: -f2)CLUSTER_INFO=$(redis-cli -h $FIRST_HOST -p $FIRST_PORT cluster info)
CLUSTER_STATE=$(echo "$CLUSTER_INFO" | grep cluster_state | cut -d: -f2)
CLUSTER_NODES_COUNT=$(echo "$CLUSTER_INFO" | grep cluster_known_nodes | cut -d: -f2)
CLUSTER_SIZE=$(echo "$CLUSTER_INFO" | grep cluster_size | cut -d: -f2)echo "集群状态: $CLUSTER_STATE"
echo "节点数量: $CLUSTER_NODES_COUNT"
echo "主节点数: $CLUSTER_SIZE"if [ "$CLUSTER_STATE" = "ok" ]; thenecho "✅ 集群配置成功!"
elseecho "❌ 集群状态异常,需要检查配置"
fiecho "=================================="
📊 监控告警配置模板
#!/bin/bash
# Redis监控告警配置脚本echo "📊 Redis监控告警配置开始..."# 创建监控脚本目录
MONITOR_DIR="/opt/redis-monitor"
mkdir -p $MONITOR_DIR# 1. 创建指标收集脚本
cat > $MONITOR_DIR/collect_metrics.sh << 'EOF'
#!/bin/bash
# Redis指标收集脚本REDIS_HOST=${1:-127.0.0.1}
REDIS_PORT=${2:-6379}
TIMESTAMP=$(date +%s)
REDIS_CLI="redis-cli -h $REDIS_HOST -p $REDIS_PORT"# 基础指标
USED_MEMORY=$($REDIS_CLI info memory | grep "^used_memory:" | cut -d: -f2)
USED_RSS=$($REDIS_CLI info memory | grep "^used_memory_rss:" | cut -d: -f2)
FRAGMENTATION_RATIO=$($REDIS_CLI info memory | grep "mem_fragmentation_ratio" | cut -d: -f2)
CONNECTED_CLIENTS=$($REDIS_CLI info clients | grep "connected_clients" | cut -d: -f2)
BLOCKED_CLIENTS=$($REDIS_CLI info clients | grep "blocked_clients" | cut -d: -f2)
INSTANTANEOUS_OPS=$($REDIS_CLI info stats | grep "instantaneous_ops_per_sec" | cut -d: -f2)
KEYSPACE_HITS=$($REDIS_CLI info stats | grep "keyspace_hits" | cut -d: -f2)
KEYSPACE_MISSES=$($REDIS_CLI info stats | grep "keyspace_misses" | cut -d: -f2)# 计算命中率
if [ "$KEYSPACE_MISSES" -gt 0 ]; thenHIT_RATE=$(echo "scale=4; $KEYSPACE_HITS / ($KEYSPACE_HITS + $KEYSPACE_MISSES)" | bc)
elseHIT_RATE=1.0000
fi# 输出指标(InfluxDB格式)
echo "redis_metrics,host=$REDIS_HOST,port=$REDIS_PORT used_memory=${USED_MEMORY}i,used_rss=${USED_RSS}i,fragmentation_ratio=$FRAGMENTATION_RATIO,connected_clients=${CONNECTED_CLIENTS}i,blocked_clients=${BLOCKED_CLIENTS}i,ops_per_sec=${INSTANTANEOUS_OPS}i,hit_rate=$HIT_RATE $TIMESTAMP"
EOFchmod +x $MONITOR_DIR/collect_metrics.sh# 2. 创建告警检查脚本
cat > $MONITOR_DIR/check_alerts.sh << 'EOF'
#!/bin/bash
# Redis告警检查脚本REDIS_HOST=${1:-127.0.0.1}
REDIS_PORT=${2:-6379}
REDIS_CLI="redis-cli -h $REDIS_HOST -p $REDIS_PORT"
ALERT_LOG="/var/log/redis-alerts.log"# 告警阈值配置
MEMORY_WARNING_THRESHOLD=80 # 内存使用率警告阈值(%)
MEMORY_CRITICAL_THRESHOLD=95 # 内存使用率严重阈值(%)
CONNECTION_WARNING_THRESHOLD=80 # 连接数使用率警告阈值(%)
FRAGMENTATION_WARNING_THRESHOLD=2.0 # 内存碎片率警告阈值
HIT_RATE_WARNING_THRESHOLD=0.8 # 命中率警告阈值
SLOWLOG_WARNING_THRESHOLD=100 # 慢查询数量警告阈值# 函数:发送告警
send_alert() {local level=$1local message=$2local timestamp=$(date '+%Y-%m-%d %H:%M:%S')echo "[$timestamp] [$level] $message" >> $ALERT_LOG# 这里可以集成邮件、短信、钉钉等告警方式# 例如:curl -X POST ... 发送到告警系统echo "ALERT [$level]: $message"
}# 检查Redis连接
if ! $REDIS_CLI ping > /dev/null 2>&1; thensend_alert "CRITICAL" "Redis服务无响应 ($REDIS_HOST:$REDIS_PORT)"exit 1
fi# 检查内存使用率
USED_MEMORY=$($REDIS_CLI info memory | grep "^used_memory:" | cut -d: -f2 | tr -d '\r')
MAX_MEMORY=$($REDIS_CLI config get maxmemory | tail -1)if [ "$MAX_MEMORY" != "0" ] && [ "$MAX_MEMORY" != "" ]; thenMEMORY_USAGE_PERCENT=$((USED_MEMORY * 100 / MAX_MEMORY))if [ $MEMORY_USAGE_PERCENT -gt $MEMORY_CRITICAL_THRESHOLD ]; thensend_alert "CRITICAL" "内存使用严重超标: ${MEMORY_USAGE_PERCENT}% (阈值: ${MEMORY_CRITICAL_THRESHOLD}%)"elif [ $MEMORY_USAGE_PERCENT -gt $MEMORY_WARNING_THRESHOLD ]; thensend_alert "WARNING" "内存使用率过高: ${MEMORY_USAGE_PERCENT}% (阈值: ${MEMORY_WARNING_THRESHOLD}%)"fi
fi# 检查连接数
CONNECTED_CLIENTS=$($REDIS_CLI info clients | grep "connected_clients" | cut -d: -f2 | tr -d '\r')
MAX_CLIENTS=$($REDIS_CLI config get maxclients | tail -1)
CONNECTION_USAGE_PERCENT=$((CONNECTED_CLIENTS * 100 / MAX_CLIENTS))if [ $CONNECTION_USAGE_PERCENT -gt $CONNECTION_WARNING_THRESHOLD ]; thensend_alert "WARNING" "连接数使用率过高: ${CONNECTION_USAGE_PERCENT}% (阈值: ${CONNECTION_WARNING_THRESHOLD}%)"
fi# 检查内存碎片率
FRAGMENTATION_RATIO=$($REDIS_CLI info memory | grep "mem_fragmentation_ratio" | cut -d: -f2 | tr -d '\r')
if (( $(echo "$FRAGMENTATION_RATIO > $FRAGMENTATION_WARNING_THRESHOLD" | bc -l) )); thensend_alert "WARNING" "内存碎片率过高: $FRAGMENTATION_RATIO (阈值: $FRAGMENTATION_WARNING_THRESHOLD)"
fi# 检查命中率
KEYSPACE_HITS=$($REDIS_CLI info stats | grep "keyspace_hits" | cut -d: -f2 | tr -d '\r')
KEYSPACE_MISSES=$($REDIS_CLI info stats | grep "keyspace_misses" | cut -d: -f2 | tr -d '\r')if [ "$KEYSPACE_HITS" -gt 0 ] && [ "$KEYSPACE_MISSES" -gt 0 ]; thenHIT_RATE=$(echo "scale=4; $KEYSPACE_HITS / ($KEYSPACE_HITS + $KEYSPACE_MISSES)" | bc)if (( $(echo "$HIT_RATE < $HIT_RATE_WARNING_THRESHOLD" | bc -l) )); thensend_alert "WARNING" "缓存命中率过低: $(echo "$HIT_RATE * 100" | bc)% (阈值: $(echo "$HIT_RATE_WARNING_THRESHOLD * 100" | bc)%)"fi
fi# 检查慢查询
SLOWLOG_LEN=$($REDIS_CLI slowlog len)
if [ $SLOWLOG_LEN -gt $SLOWLOG_WARNING_THRESHOLD ]; thensend_alert "WARNING" "慢查询数量过多: $SLOWLOG_LEN (阈值: $SLOWLOG_WARNING_THRESHOLD)"
fi# 检查主从同步状态
ROLE=$($REDIS_CLI info replication | grep "^role:" | cut -d: -f2 | tr -d '\r')
if [ "$ROLE" = "slave" ]; thenMASTER_LINK_STATUS=$($REDIS_CLI info replication | grep "master_link_status:" | cut -d: -f2 | tr -d '\r')if [ "$MASTER_LINK_STATUS" != "up" ]; thensend_alert "CRITICAL" "主从同步连接断开"fi
fi
EOFchmod +x $MONITOR_DIR/check_alerts.sh# 3. 创建定时任务
echo "📅 配置定时监控任务..."# 添加crontab任务
CRON_JOBS="
# Redis指标收集 - 每分钟执行一次
* * * * * $MONITOR_DIR/collect_metrics.sh >> /var/log/redis-metrics.log 2>&1# Redis告警检查 - 每5分钟执行一次
*/5 * * * * $MONITOR_DIR/check_alerts.sh# Redis健康检查 - 每小时执行一次
0 * * * * /opt/redis-monitor/redis_health_check.sh > /var/log/redis-health-$(date +\%Y\%m\%d).log 2>&1
"echo "$CRON_JOBS" | crontab -# 4. 创建监控仪表板配置
echo "📊 创建监控仪表板配置..."cat > $MONITOR_DIR/grafana-dashboard.json << 'EOF'
{"dashboard": {"title": "Redis监控仪表板","panels": [{"title": "内存使用情况","targets": [{"expr": "redis_used_memory_bytes","legendFormat": "已使用内存"}]},{"title": "QPS","targets": [{"expr": "rate(redis_commands_total[1m])","legendFormat": "每秒操作数"}]},{"title": "连接数","targets": [{"expr": "redis_connected_clients","legendFormat": "当前连接数"}]},{"title": "命中率","targets": [{"expr": "rate(redis_keyspace_hits_total[5m]) / (rate(redis_keyspace_hits_total[5m]) + rate(redis_keyspace_misses_total[5m]))","legendFormat": "缓存命中率"}]}]}
}
EOFecho "✅ 监控告警配置完成!"
echo "📁 监控脚本位置: $MONITOR_DIR"
echo "📋 告警日志位置: /var/log/redis-alerts.log"
echo "📊 指标日志位置: /var/log/redis-metrics.log"
echo ""
echo "🔧 下一步操作:"
echo "1. 根据实际需求调整告警阈值"
echo "2. 配置告警通知方式(邮件、短信等)"
echo "3. 部署Grafana仪表板"
echo "4. 验证监控脚本运行正常"
🎯 九、故障排查最佳实践
📋 排查优先级清单
-
立即检查项(< 1分钟)
# 快速状态检查 redis-cli ping redis-cli info server | head -5 redis-cli info memory | grep used_memory_human redis-cli info clients | grep connected_clients
-
紧急问题排查(< 5分钟)
# 慢查询检查 redis-cli slowlog get 10# 内存状况检查 redis-cli info memory | grep -E "(used_memory|fragmentation|maxmemory)"# 连接状态检查 redis-cli client list | wc -l redis-cli config get maxclients
-
深度排查(< 15分钟)
# 持久化状态 redis-cli info persistence# 主从复制状态 redis-cli info replication# 系统资源检查 top -p $(pgrep redis-server) iostat -x 1 3
🚨 告警响应流程
📚 常见问题快速解决方案
问题类型 | 快速诊断 | 解决方案 |
---|---|---|
连接超时 | redis-cli ping | 检查网络/防火墙/Redis服务状态 |
内存不足 | info memory | 清理过期key/调整maxmemory |
响应变慢 | slowlog get | 优化慢查询/检查阻塞操作 |
主从断开 | info replication | 重建主从关系/检查网络 |
集群异常 | cluster info | 修复故障节点/重新分配槽位 |
📝 十、总结与建议
✅ 生产环境运维要点
-
预防为主
- 建立完善的监控告警体系
- 定期进行健康检查和性能测试
- 制定详细的运维操作规范
-
快速响应
- 熟练掌握常用诊断命令
- 建立故障处理标准流程
- 准备应急处理脚本
-
持续优化
- 定期分析性能指标趋势
- 根据业务增长调整配置
- 不断完善监控和告警规则
🔧 推荐的运维工具
- 监控: Prometheus + Grafana + Redis Exporter
- 告警: AlertManager + 企业通知系统
- 日志: ELK Stack (Elasticsearch + Logstash + Kibana)
- 自动化: Ansible + Shell脚本
- 备份: 定时RDB + AOF + 异地备份
📞 紧急联系清单
# 生产环境紧急处理清单
echo "📞 Redis紧急故障联系清单"
echo "================================"
echo "1. 数据库团队: xxx-xxxx-xxxx"
echo "2. 运维团队: xxx-xxxx-xxxx"
echo "3. 架构师: xxx-xxxx-xxxx"
echo "4. 技术经理: xxx-xxxx-xxxx"
echo ""
echo "🔧 重要系统信息:"
echo "Redis版本: $(redis-cli info server | grep redis_version)"
echo "配置文件: /etc/redis/redis.conf"
echo "数据目录: $(redis-cli config get dir | tail -1)"
echo "日志文件: /var/log/redis/redis-server.log"
echo "================================"
📎 附录:命令速查表
🔍 诊断命令速查
# 基础状态
redis-cli ping # 连接测试
redis-cli info server # 服务器信息
redis-cli info memory # 内存信息
redis-cli info stats # 统计信息
redis-cli info clients # 客户端信息
redis-cli info replication # 复制信息
redis-cli info persistence # 持久化信息# 性能分析
redis-cli slowlog get 10 # 慢查询日志
redis-cli --latency # 延迟测试
redis-cli --latency-history # 延迟历史
redis-cli --bigkeys # 大key扫描
redis-cli monitor # 实时监控
redis-cli --stat # 实时统计# 连接管理
redis-cli client list # 客户端列表
redis-cli client kill ip 192.168.1.100 # 杀死连接
redis-cli client kill idle 3600 # 杀死空闲连接# 集群管理
redis-cli cluster info # 集群信息
redis-cli cluster nodes # 节点信息
redis-cli cluster slots # 槽位信息
redis-cli --cluster check host:port # 集群检查
redis-cli --cluster fix host:port # 集群修复# 内存管理
redis-cli memory usage key # key内存使用
redis-cli memory purge # 内存整理
redis-cli memory stats # 内存统计
⚙️ 配置命令速查
# 内存配置
redis-cli config set maxmemory 4gb
redis-cli config set maxmemory-policy allkeys-lru
redis-cli config set lazyfree-lazy-eviction yes# 连接配置
redis-cli config set maxclients 1000
redis-cli config set timeout 300
redis-cli config set tcp-keepalive 300# 持久化配置
redis-cli config set save "900 1 300 10 60 1000"
redis-cli config set appendonly yes
redis-cli config set appendfsync everysec# 主从配置
redis-cli slaveof 192.168.1.10 6379 # 设置主库
redis-cli slaveof no one # 取消主从# 查看配置
redis-cli config get "*" # 所有配置
redis-cli config get maxmemory # 特定配置
redis-cli config rewrite # 保存配置
🎉 手册编写完成!
本手册涵盖了Redis生产环境的完整故障排查流程,包含详细的中文说明和实用的脚本工具。建议收藏此手册,在遇到Redis问题时按照手册步骤进行排查,可以快速定位和解决大部分生产环境问题。
💡 使用建议:
- 将此手册保存为本地文件,方便紧急情况下快速查阅
- 根据实际环境调整脚本中的IP地址、端口、路径等参数
- 定期更新和完善手册内容,结合实际故障案例优化排查流程
- 团队成员应熟练掌握基础诊断命令,提高故障响应效率