Redis 的性能問題通常源于配置不當、數據結構誤用、資源瓶頸或架構缺陷。以下是 Redis 常見的性能問題及優化方案,結合線上經驗整理:
🧠 ?一、內存相關問題?
?1. 內存不足(OOM)??
- ?現象?:
OOM errors
、響應超時、節點崩潰。 - ?原因?:
- 數據量超過
maxmemory
限制。 - 未設置合理淘汰策略(如
allkeys-lru
)。
- 數據量超過
- ?解決?:
- 監控內存使用(
INFO memory
),預留 20%~30% 緩沖。 - 設置
maxmemory-policy
(推薦volatile-lru
或allkeys-lru
)。 - 拆分大 Key(見下文),開啟內存碎片整理(
activedefrag yes
)。
- 監控內存使用(
?2. 內存碎片過高?
- ?現象?:
mem_fragmentation_ratio > 1.5
(INFO memory
查看),內存浪費嚴重。 - ?原因?:頻繁修改、刪除 Key(如 List 元素 pop/push)。
- ?解決?:
- 開啟碎片整理:
activedefrag yes
+ 調整active-defrag-*
參數。 - 升級 Redis 6.2+(優化 jemalloc 碎片管理)。
- 避免頻繁刪除大 Key,重啟節點釋放碎片(謹慎操作)。
- 開啟碎片整理:
? ?二、CPU 與延遲問題?
?1. CPU 跑滿(100%)??
- ?現象?:響應延遲飆升,
slowlog
大量記錄。 - ?原因?:
- ?復雜命令?:
KEYS *
、FLUSHALL
、大數據集SINTER
/ZUNIONSTORE
。 - ?過期 Key 集中清理?(
active-expire-cycle
占用)。 - ?RDB/AOF 持久化?:
bgsave
或rewriteaof
時 fork 阻塞。
- ?復雜命令?:
- ?解決?:
- ?禁用高危命令?:
rename-command KEYS ""
。 - 避免單 Key 過大(拆分集合類型)。
- 調整持久化策略:AOF 改為
everysec
,減少 RDB 頻率。 - 升級 SSD 磁盤(降低
fork
阻塞時間)。
- ?禁用高危命令?:
?2. 慢查詢(Slow Query)??
- ?現象?:
SLOWLOG get
記錄大量 >10ms 操作。 - ?原因?:
- ?大 Key 操作?:獲取 10MB 的 String,遍歷 100 萬成員的 Set。
- ?不合理管道?:
PIPELINE
內堆積過多命令阻塞響應。
- ?解決?:
- ?所有操作時間復雜度必須為 O(1) 或 O(logN)?。
- 禁止
HGETALL
、SMEMBERS
→ 用HSCAN
/SSCAN
分批次獲取。 - 控制 Pipeline 命令數量(一般不超過 100/次)。
- 使用
redis-cli --latency
檢測網絡延遲問題。
📦 ?三、數據模型問題?
?1. 大 Key(Big Key)??
- ?定義?:
- String 類型 > 10 KB
- 集合類型(Hash/List/Set/ZSet)元素 > 5,000
- ?風險?:阻塞網絡、內存溢出、持久化超時。
- ?排查?:
redis-cli --bigkeys
(生產慎用,改用離線分析工具)。 - ?優化?:
- ?拆分 Key?:Hash →
user:{id}:profile_base
+user:{id}:profile_detail
。 - ?壓縮?:
gzip
壓縮 String 值(需權衡 CPU)。 - ?分片讀取?:
ZRANGEBYSCORE
→ZSCAN
分批操作。
- ?拆分 Key?:Hash →
?2. 熱 Key(Hot Key)??
- ?現象?:單 Key QPS > 5,000,節點流量不均。
- ?解決?:
- ?客戶端緩存?:
Redis 6.0+
Client-side Caching(CLIENT TRACKING
)。 - ?讀分離?:增加副本節點分擔讀壓力。
- ?本地緩存?:在應用層用 Caffeine 或 Guava Cache 擋一層。
- ?分片存儲?:將 Key 復制多份(如
hot_key_v1
,hot_key_v2
),輪詢訪問。
- ?客戶端緩存?:
📡 ?四、網絡與連接問題?
?1. 連接數耗盡?
- ?現象?:
ERR max number of clients reached
,新連接失敗。 - ?原因?:
maxclients
設置過低(默認 10,000)。- 客戶端未釋放連接(如連接池泄漏)。
- ?解決?:
- 調高
maxclients
(需考慮系統句柄數限制)。 - 使用連接池(如 Lettuce、Jedis),檢查泄漏(
CLIENT LIST
看 idle 時間)。
- 調高
?2. 網絡擁堵?
- ?現象?:
throughput
下降,延遲抖動。 - ?原因?:
- 單節點流量超過網卡上限(如 10 Gbps)。
- 跨機房訪問(網絡延遲增加)。
- ?解決?:
- 分片集群:增加節點分攤流量。
- 同機房部署:避免跨 AZ 訪問。
- 升級網絡:萬兆網卡或 RDMA。
💾 ?五、持久化問題?
?1. AOF 阻塞寫入?
- ?現象?:
aof_delayed_fsync
計數上升,主線程阻塞。 - ?原因?:
appendfsync always
每次寫入同步磁盤(性能極差)。 - ?解決?:改為
appendfsync everysec
(平衡性能與安全)。
?2. RDB fork 超時?
- ?現象?:
bgsave
時主線程卡頓數秒。 - ?原因?:數據集大 + 磁盤慢,
fork()
耗時過長。 - ?優化?:
- 使用 SSD 磁盤。
- 控制
save
頻率(如從save 60 10000
調整為save 300 1000
)。 - 關閉透明大頁(
THP
):echo never > /sys/kernel/mm/transparent_hugepage/enabled
。
?? ?六、集群與高可用問題?
?1. 數據傾斜?
- ?表現?:部分節點內存/CPU 使用率遠超其他節點。
- ?解決?:
- ?均勻分片?:避免使用單一
hash tag
(如{user123}
)。 - 擴容集群:增加分片數。
- 手動遷移 Slot(
CLUSTER SETSLOT
+MIGRATE
)。
- ?均勻分片?:避免使用單一
?2. 腦裂(Split-Brain)??
- ?現象?:主從切換后數據丟失。
- ?預防?:
- 設置
min-slaves-to-write 1
(至少 1 個從節點同步才可寫)。 - 合理配置
cluster-node-timeout
(默認 15s,避免過早切換)。
- 設置
🔍 ?診斷工具速查表?
?工具/命令? | ?用途? |
---|---|
INFO memory | 檢查內存使用與碎片率 |
SLOWLOG get | 抓取慢查詢命令 |
redis-cli --bigkeys | 掃描大 Key(慎用線上) |
redis-cli --hotkeys | 探測熱 Key(需開啟 LFU) |
MONITOR | 實時抓取命令(僅調試,影響性能) |
?RedisInsight? | 官方可視化監控(內存/命令/集群) |
?Prometheus+Grafana? | 構建實時監控大盤 |
? ?性能優化總結?
- ?內存?:防 OOM + 控碎片 + 拆大 Key
- ?CPU?:避免復雜命令 + 優化持久化策略
- ?數據模型?:禁止遍歷操作 + 讀寫分離拆熱 Key
- ?網絡?:連接池管理 + 集群分片均勻
- ?持久化?:
everysec
代替always
,SSD 減少fork
阻塞 - ?集群?:防傾斜 + 防腦裂 + 定期擴縮容
?關鍵原則?:?所有命令必須 O(1) 時間復雜度,網絡往返次數比數據大小更影響性能!??
建議結合 監控指標
+ 慢日志
定位瓶頸,優先解決大 Key、熱 Key 和持久化阻塞問題。遇到高并發場景,本地緩存 + 讀寫分離是性價比最高的方案。