Redis 快取策略教學:Cache-Aside、Write-Through 到實戰踩坑全紀錄
如果你問我後端最重要的效能優化是什麼,我的答案永遠是快取。但快取絕不是寫個 redis.set() 和 redis.get() 就搞定的事。選錯策略,輕則資料不一致,重則快取雪崩整個系統掛掉。
今天我把 Redis 四大快取策略一次講清楚,加上我在實際專案中踩過的坑。如果你之前看過我的 Docker Compose 多容器部署教學,你應該知道 Redis 通常就是 Docker Compose 裡的第一個服務。
為什麼你需要快取策略
先釐清一個觀念:快取不只是「讓東西變快」。一個好的快取策略要同時處理三個問題:
- 資料一致性:快取裡的資料要跟資料庫同步到什麼程度?
- 讀寫效能:是讀多寫少,還是寫入也很頻繁?
- 容錯能力:Redis 掛了怎麼辦?
不同的業務場景,這三個問題的優先順序不同,所以才需要不同的策略。
Cache-Aside 旁路快取
Cache-Aside 是最常見也最通用的策略,又叫 Lazy Loading。流程很直覺:
- 應用程式先查 Redis
- Cache Hit → 直接回傳
- Cache Miss → 查資料庫 → 寫入 Redis → 回傳
- 資料更新時,刪除對應的快取 key
適用場景
- 讀多寫少的資料(使用者個人資料、商品目錄、文章內容)
- 能容忍短暫資料不一致的場景
- 需要高可用性(Redis 掛了只是變慢,不會錯)
關鍵踩坑:更新時要「刪」不要「改」
這是我剛接觸快取時犯的錯。直覺上,資料更新時應該同步更新快取對吧?但如果兩個請求同時更新同一筆資料,可能出現競態條件導致快取和 DB 不一致。刪除快取就不會有這個問題,因為下次讀取會從 DB 拿最新值重新快取。
Write-Through 寫穿快取
Write-Through 是「先寫 DB,同步寫快取」的策略。每次寫入操作都會同時更新兩邊。
適用場景
- 需要強一致性的資料(帳戶餘額、庫存數量)
- 寫入頻率不高的場景
- 不能容忍任何資料不一致的業務邏輯
代價
每次寫入都會增加 2-6 毫秒的延遲(多了一次 Redis 寫入)。如果寫入量大,這個開銷會很明顯。
Write-Behind 寫回快取
Write-Behind(也叫 Write-Back)是 Write-Through 的非同步版本:先寫快取,然後異步批量寫入 DB。
適用場景
- 寫入極其頻繁的場景(即時計數器、瀏覽次數、點讚數)
- 能容忍少量資料遺失的業務
風險
如果 Redis 在異步寫入 DB 之前掛了,那些還沒同步的資料就丟了。所以絕對不要用在金融交易這種場景。
TTL 與快取雪崩防護
不管用哪種策略,都必須設定 TTL(Time To Live)。我的建議:
| 資料類型 | 建議 TTL |
|---|---|
| 主資料(使用者、商品) | 1 小時 |
| Session / 個人偏好 | 15 分鐘 |
| 聚合統計資料 | 5 分鐘 |
| 熱門排行榜 | 10 分鐘 |
防止快取雪崩(Cache Stampede)
當一個熱門 key 的 TTL 到期,大量請求同時打到 DB,就是快取雪崩。解法有三個:
- 加隨機 jitter:TTL 不要設固定值,加上隨機偏移(例如 3600 ± 300 秒)
- 分散式鎖:同一個 key 只讓一個請求回源查 DB,其他等結果
- 提前刷新:在 TTL 過期前就異步刷新,永遠不讓快取真正過期
實戰:Node.js + Redis 範例
以下是 Cache-Aside 模式的典型實作:
async function getUserById(userId) {
const cacheKey = \`user:\${userId}\`;
const cached = await redis.get(cacheKey);
if (cached) return JSON.parse(cached);
const user = await db.query('SELECT * FROM users WHERE id = $1', [userId]);
const ttl = 3600 + Math.floor(Math.random() * 600);
await redis.setex(cacheKey, ttl, JSON.stringify(user));
return user;
}
async function updateUser(userId, data) {
await db.query('UPDATE users SET ... WHERE id = $1', [userId]);
await redis.del(\`user:\${userId}\`);
}策略選擇速查表
| 場景 | 推薦策略 | 原因 |
|---|---|---|
| 商品目錄、文章列表 | Cache-Aside | 讀多寫少,容忍短暫不一致 |
| 帳戶餘額、庫存 | Write-Through | 需要強一致性 |
| 瀏覽計數、點讚數 | Write-Behind | 寫入頻繁,容忍少量遺失 |
| Session 管理 | Cache-Aside + 短 TTL | 安全性要求高,TTL 短 |
快取策略沒有萬能解法,關鍵是理解你的讀寫比例和一致性需求。如果還在猶豫,Cache-Aside 是最安全的起點,等遇到具體問題再調整也不遲。
你可能也喜歡
探索其他領域的精選好文