1. 緩存三大問題及解決方案
問題 | 場景 | 后果 | 常用解決方案 |
---|---|---|---|
緩存穿透 | 請求的數據在緩存和數據庫中都不存在(惡意攻擊或查詢異常 ID) | 每次請求都會打到數據庫,導致 DB 壓力驟增 | - 緩存空值(短期緩存不存在的 key) - 布隆過濾器(提前判斷 key 是否存在) - 接口參數校驗、限流 |
緩存擊穿 | 熱點 key 過期瞬間,大量請求同時訪問 | 同一時間大量請求打到數據庫,可能壓垮 DB | - 互斥鎖 / 分布式鎖(第一個請求構建緩存,其它等待) - 邏輯過期(業務側判斷過期,異步更新) - 提前刷新緩存 |
緩存雪崩 | 大量 key 在同一時間過期(比如統一設置了相同 TTL) | 瞬時緩存失效,所有請求直達 DB,造成雪崩 | - 過期時間隨機化(TTL + 隨機值) - 多級緩存(本地緩存 + 分布式緩存) - 限流 + 服務降級 |
2. 如何保證 Redis 的高并發
Redis 本身是單線程處理命令(IO 多路復用 + 內存操作快),但要在高并發場景下保持性能,需要從以下幾方面優化:
網絡層優化
使用 pipeline 批量發送命令減少 RTT
合理配置連接池,避免頻繁建立連接
數據結構選擇
選擇合適的 Redis 數據類型(如 hash 存儲對象、zset 排序等)減少 key 數量
避免大 key(拆分成多個小 key)
分片與集群
使用 Redis Cluster 做數據分片,分攤 QPS 壓力
業務端可做讀寫分離(主寫,從讀)
熱點 key 優化
本地緩存(Caffeine / Guava)+ Redis 二級緩存
預熱熱點數據,減少直接訪問 DB
持久化與備份
結合 RDB + AOF(混合持久化)減少阻塞
合理調優 save、appendfsync 等參數
3. Redis 如何保證原子性
Redis 的原子性是依賴其單線程命令執行模型,以及事務機制:
單命令天然原子性
Redis 單線程按順序執行命令,不會被中斷
例如 INCR key、HSET key field value 是天然原子操作
事務(MULTI/EXEC)
將多個命令放到事務中執行,保證要么全執行,要么都不執行(但事務內命令不會回滾)
Lua 腳本
使用 EVAL 在服務端執行一段 Lua 腳本,腳本中所有操作是原子性的
常用于復雜的原子性業務邏輯(如扣庫存 + 記錄日志)加粗樣式