2.2 本地快取與分散式快取:Memcached / Redis / Tair#
從一個問題開始#
2.1 節加了快取,商品頁快如飛。但很快兩個新問題冒出來:第一,加了第二台 Web 機器後,兩台機器的快取各存一份,改價後一台新一台舊;第二,有人把大物件塞進 JVM 堆做快取,一個 Full GC 全站卡三秒。
這就是快取的第一個選型題:快取放在應用進程裡(本地快取),還是放在獨立服務裡(分散式快取)?
本地快取:快,但各自為政#
本地快取就是 JVM 裡的一個 HashMap(如 Guava Cache、Caffeine):讀寫都在進程內,延遲最低(奈秒級),但每台機器各存一份。
flowchart LR
subgraph W1[Web 1]
L1[本地快取<br/>item:1 = 100元]
end
subgraph W2[Web 2]
L2[本地快取<br/>item:1 = 90元]
end
L1 & L2 --> DB[(MySQL<br/>最新價 90元)]改價後 Web 2 回源拿到新價,Web 1 的舊快取要等 TTL 過期才刷新——不一致窗口 × 機器數量。機器越多,髒數據越多。這就是本地快取的原罪:沒有共享,就沒有一致。
分散式快取:獨立服務,共享記憶體#
分散式快取把記憶體抽出來做成獨立集群,所有 Web 節點共享同一份數據。代表選手有三位:
flowchart LR
W1[Web 1] -->|TCP| C[(分散式快取集群)]
W2[Web 2] -->|TCP| C
W3[Web 3] -->|TCP| C
C -->|回源| DB[(MySQL)]| 特性 | Memcached | Redis | Tair(阿里自研) |
|---|---|---|---|
| 資料結構 | 純 KV 字串 | String/Hash/List/Set/ZSet/Stream | KV + 多種引擎(含持久化) |
| 持久化 | 無 | RDB + AOF | 有(LDB 引擎落盤) |
| 集群方案 | 客戶端一致性雜湊 | Sentinel / Cluster 分片 | 自動分區 + 多機房容災 |
| 適用場景 | 簡單 KV、大對象快取 | 排行榜、計數、分散式鎖、會話 | 電商大促、圖片特徵等自研場景 |
| 記憶體效率 | 高(slab) | 中等(物件開銷大) | 按場景優化 |
一句話選型:簡單 KV 用 Memcached,玩資料結構用 Redis,阿里體量自研 Tair。淘寶走的正是第三條路,但思想與 Redis 相通。
兩者不是二選一:分層快取#
實務上成熟的答案是兩級一起用:L1 本地快取擋最熱的 10%(TTL 幾秒),L2 分散式快取擋次熱的 80%(TTL 幾分鐘),最後才回源 DB。
// 分層讀:L1 → L2 → DB
Item item = caffeine.get(key); // L1:進程內,3 秒過期
if (item == null) {
item = redis.get(key); // L2:共享,5 分鐘過期
if (item == null) {
item = itemDao.findById(itemId); // DB:最後防線
redis.set(key, item, 300);
}
caffeine.put(key, item, 3);
}
flowchart TD
R[請求] --> L1{L1 本地命中?}
L1 -->|是| OK[直接返回<br/>微秒級]
L1 -->|否| L2{L2 Redis 命中?}
L2 -->|是| F1[回填 L1 後返回]
L2 -->|否| DB[查 DB 並逐級回填]代價是复杂度:兩層 TTL、兩層失效通知。但收益是 DB 幾乎收不到讀流量——大促就靠這套組合活下來。
本章小結#
- 本地快取最快但不共享,多台機器之間必然出現髒數據分歧
- 分散式快取讓所有 Web 共享同一份記憶體,是集群時代的標配
- Memcached 專精簡單 KV,Redis 勝在資料結構,Tair 是阿里的規模化答案
- 實務正解是分層快取:L1 本地擋最熱數據,L2 分散式擋次熱數據
- 層數越多,不一致窗口與運維複雜度越高,為 2.3、2.4 節埋下伏筆
想一想#
- 兩台 Web 都用本地快取,改價後為什麼會出現「同一件商品兩種價格」?怎麼復現?
- L1 只敢設 3 秒 TTL、L2 敢設 5 分鐘,背後的理由是什麼?
- 計數器、排行榜這類需求為什麼 Redis 比 Memcached 合適?試舉一個具體命令。
中英術語對照#
| 中文 | 英文 |
|---|---|
| 本地快取 / 分散式快取 | Local Cache / Distributed Cache |
| 分層快取 | Multi-level Cache |
| 一致性雜湊 | Consistent Hashing |
| 資料結構 / 持久化 | Data Structure / Persistence |
| 不一致窗口 | Inconsistency Window |