150 lines
4.8 KiB
Bash
150 lines
4.8 KiB
Bash
#!/bin/bash
|
|
|
|
# Redis 内存使用诊断脚本
|
|
# 分析 Redis 内存占用情况并提供优化建议
|
|
|
|
echo "=========================================="
|
|
echo "Redis 内存使用诊断报告"
|
|
echo "=========================================="
|
|
echo "生成时间: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
echo ""
|
|
|
|
# 检查 Redis 是否运行
|
|
if ! redis-cli ping > /dev/null 2>&1; then
|
|
echo "错误: Redis 未运行或无法连接"
|
|
exit 1
|
|
fi
|
|
|
|
echo "1. 内存使用概览"
|
|
echo "----------------------------------------"
|
|
redis-cli INFO memory | grep -E "used_memory_human|used_memory_peak_human|maxmemory_human|mem_fragmentation_ratio|used_memory_rss_human"
|
|
|
|
echo ""
|
|
echo "2. 配置信息"
|
|
echo "----------------------------------------"
|
|
redis-cli CONFIG GET maxmemory | xargs printf "最大内存限制: %s = %s\n"
|
|
redis-cli CONFIG GET maxmemory-policy | xargs printf "淘汰策略: %s = %s\n"
|
|
|
|
echo ""
|
|
echo "3. 数据库统计"
|
|
echo "----------------------------------------"
|
|
printf "Key 总数: "
|
|
redis-cli DBSIZE
|
|
|
|
echo ""
|
|
echo "4. 各类型 Key 数量分布"
|
|
echo "----------------------------------------"
|
|
echo "注意: 此操作可能耗时较长..."
|
|
|
|
# 统计不同前缀的 key 数量
|
|
declare -A key_counts
|
|
|
|
while IFS= read -r key; do
|
|
prefix=$(echo "$key" | cut -d':' -f1)
|
|
((key_counts[$prefix]++))
|
|
done < <(redis-cli --scan)
|
|
|
|
echo "前缀统计:"
|
|
for prefix in "${!key_counts[@]}"; do
|
|
printf " %-30s %d 个\n" "$prefix:" "${key_counts[$prefix]}"
|
|
done | sort -k2 -rn | head -20
|
|
|
|
echo ""
|
|
echo "5. 最大的 Key (Top 10)"
|
|
echo "----------------------------------------"
|
|
redis-cli --bigkeys 2>/dev/null | grep -A 20 "Biggest"
|
|
|
|
echo ""
|
|
echo "6. 没有过期时间的 Key 统计"
|
|
echo "----------------------------------------"
|
|
no_ttl_count=0
|
|
total_keys=$(redis-cli DBSIZE | awk '{print $1}')
|
|
|
|
# 采样检查 (最多检查1000个key)
|
|
sample_size=1000
|
|
checked=0
|
|
no_ttl_samples=""
|
|
|
|
while IFS= read -r key && [ $checked -lt $sample_size ]; do
|
|
ttl=$(redis-cli TTL "$key")
|
|
if [ "$ttl" = "-1" ]; then
|
|
((no_ttl_count++))
|
|
if [ $no_ttl_count -le 5 ]; then
|
|
no_ttl_samples="$no_ttl_samples\n $key"
|
|
fi
|
|
fi
|
|
((checked++))
|
|
done < <(redis-cli --scan)
|
|
|
|
if [ $checked -ge $total_keys ]; then
|
|
echo "检查了全部 $total_keys 个 key"
|
|
echo "没有过期时间的 key: $no_ttl_count 个 ($(awk "BEGIN {printf \"%.1f\", $no_ttl_count/$total_keys*100}")%)"
|
|
else
|
|
echo "采样检查了 $checked 个 key (总数: $total_keys)"
|
|
echo "采样中没有过期时间的 key: $no_ttl_count 个 ($(awk "BEGIN {printf \"%.1f\", $no_ttl_count/$checked*100}")%)"
|
|
fi
|
|
|
|
if [ $no_ttl_count -gt 0 ]; then
|
|
echo -e "示例:$no_ttl_samples"
|
|
fi
|
|
|
|
echo ""
|
|
echo "7. 内存使用率评估"
|
|
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 | tr -d '\r')
|
|
|
|
if [ "$max_memory" = "0" ]; then
|
|
echo "⚠️ 警告: 未设置最大内存限制!"
|
|
echo " 建议: 执行 ./configure_redis_memory.sh 设置内存限制"
|
|
else
|
|
usage_percent=$(awk "BEGIN {printf \"%.1f\", $used_memory/$max_memory*100}")
|
|
echo "内存使用率: $usage_percent%"
|
|
|
|
if (( $(echo "$usage_percent > 90" | bc -l) )); then
|
|
echo "🔴 严重: 内存使用率超过 90%!"
|
|
echo " 建议: 立即清理缓存或增加内存限制"
|
|
elif (( $(echo "$usage_percent > 80" | bc -l) )); then
|
|
echo "🟡 警告: 内存使用率超过 80%"
|
|
echo " 建议: 清理不必要的缓存"
|
|
elif (( $(echo "$usage_percent > 70" | bc -l) )); then
|
|
echo "🟢 正常: 内存使用率在合理范围内"
|
|
else
|
|
echo "🟢 良好: 内存使用率较低"
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
echo "8. 优化建议"
|
|
echo "----------------------------------------"
|
|
|
|
# 检查是否设置了最大内存
|
|
if [ "$max_memory" = "0" ]; then
|
|
echo "✓ 设置 Redis 最大内存限制"
|
|
echo " 命令: redis-cli CONFIG SET maxmemory 512mb"
|
|
fi
|
|
|
|
# 检查是否有很多没有过期时间的 key
|
|
if [ $no_ttl_count -gt $(($checked / 2)) ]; then
|
|
echo "✓ 大量 key 没有过期时间,建议设置 TTL"
|
|
echo " 自动修复: 应用中的 RedisCacheCleanupTask 会自动处理"
|
|
fi
|
|
|
|
# 检查淘汰策略
|
|
eviction_policy=$(redis-cli CONFIG GET maxmemory-policy | tail -1 | tr -d '\r')
|
|
if [ "$eviction_policy" = "noeviction" ]; then
|
|
echo "✓ 当前淘汰策略为 noeviction,建议改为 volatile-lru"
|
|
echo " 命令: redis-cli CONFIG SET maxmemory-policy volatile-lru"
|
|
fi
|
|
|
|
echo ""
|
|
echo "=========================================="
|
|
echo "诊断完成!"
|
|
echo "=========================================="
|
|
echo ""
|
|
echo "快速操作:"
|
|
echo "1. 配置 Redis 内存: ./configure_redis_memory.sh"
|
|
echo "2. 清理 Redis 数据: redis-cli FLUSHDB (谨慎!)"
|
|
echo "3. 重启应用以应用新的缓存策略"
|