一台 Redis 實例在極短時間內吞噬數十 GB 記憶體,最終因 Swap 暴增而宕機。由於業務背景複雜,一時難以鎖定「兇手」。
直覺認為有大 Key 佔用空間,DBA 使用 redis-rdb-tools 分析 RDB 快照,雖發現幾個大 Key,但經核實均非主因,排查陷入僵局。
即使單個 Key 體積不大,若同模式 Key 數量極大,總佔用同樣驚人。目標轉為:找出佔用總記憶體最大的 Key 模式。為避免生產環境風險,在測試機通過「刪除可疑 Key + 觀察記憶體變化」驗證假設。
初嘗 KEYS foo:* | xargs redis-cli DEL,結果服務器直接掛了 —— KEYS 會阻塞主線程掃描全庫,Key 數量大時極其危險。
必須使用 SCAN 游標式迭代,每次僅遍歷少量 Key,對效能影響可控。
<?php
$redis = new Redis();
$redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY);
$match = 'foo:*';
$count = 10000;
while ($keys = $redis->scan($it, $match, $count)) {
$redis->del($keys);
}
?>
SCAN_RETRY 自動處理游標迴圈。$count 控制每次迭代返回 Key 數量,平衡速度與阻塞風險。watch -d -n 1 'redis-cli INFO | grep memory'
刪除過程中觀察 used_memory、used_memory_human 下降曲線,快速確認目標模式。
MONITOR 抓取實時命令流,取樣分析高頻前綴。SCAN 0 MATCH * COUNT 10000 多次取樣統計前綴分佈。INFO 中 db0:keys=... 總 Key 數變化趨勢,異常增長往往預示洩漏。KEYS 或 FLUSHALL。maxmemory-policy 避免 OOM,並對關鍵指標(記憶體、Key 總數、命中率)設置告警。