Memcached 作為中間緩存層,位於應用與 MySQL 之間,吸收高頻讀請求,降低數據庫 QPS 壓力,提升響應延遲。
┌─────────┐ ┌──────────────┐ ┌─────────┐
│ App │────▶│ Memcached │────▶│ MySQL │
│ (Client)│ │ (Cache) │ │ (DB) │
└─────────┘ └──────────────┘ └─────────┘
│ │ │
│ 1. GET key │ │
│◀──────────────│ │
│ │ │
│ 2. MISS │ │
│──────────────▶│ │
│ │ 3. SELECT ... │
│ │───────────────────▶│
│ │ │
│ │ 4. Result Set │
│ │◀───────────────────│
│ │ │
│ │ 5. SET key, value │
│ │ (TTL) │
│ │ │
│ 6. Return │ │
│◀──────────────│ │
| 操作 | Memcached 動作 | MySQL 動作 | 關鍵點 |
|---|---|---|---|
| 查詢 (SELECT) | GET key → 命中返回 / 未命中觸發回源 | 未命中時執行查詢 | 回源後 SET key value TTL 回填緩存 |
| 更新 (UPDATE) | DELETE key (或 SET 新值) | 執行更新 | 先更新 DB,再刪緩存,避免臟讀 |
| 新增 (INSERT) | DELETE key (相關列表緩存) | 執行插入 | 列表/聚合緩存必須失效 |
| 刪除 (DELETE) | DELETE key (相關緩存) | 執行刪除 | 同更新策略 |
// PHP Memcached 擴展範例
$mc = new Memcached();
$mc->addServer('127.0.0.1', 11211);
$key = 'thread_2009';
$ttl = 100; // 秒
// 1. 讀取
$data = $mc->get($key);
if ($data === false) {
// 回源查詢
$data = $db->query("SELECT * FROM threads WHERE id=2009")->fetch();
$mc->set($key, $data, $ttl);
}
// 2. 更新
$db->execute("UPDATE threads SET views=views+1 WHERE id=2009");
$mc->delete($key); // 下次讀取自動回源
// 3. 新增
$db->execute("INSERT INTO threads ... VALUES (...)");
$mc->delete('thread_list_latest'); // 列表緩存失效
// 4. 刪除
$db->execute("DELETE FROM threads WHERE id=2009");
$mc->delete($key);
$mc->delete('thread_list_latest');
appname:module:entity:id (如 forum:thread:2009)v2:forum:thread:2009SET key '' 30 避免重複回源ttl + rand(0, 300) 錯峰失效| 模式 | 一致性 | 性能 | 複雜度 | 適用場景 |
|---|---|---|---|---|
| Cache-Aside (旁路緩存) | 最終一致 | 高 | 低 | 讀多寫少、容忍秒級不一致 |
| Read/Write Through | 強一致 | 中 | 高 | 金融核心、需強一致 |
| Write Behind (異步寫回) | 弱一致 | 極高 | 極高 | 日誌、計數器、可丟失數據 |
主流選擇:Cache-Aside + 先更新 DB,再刪緩存 (雙刪策略:更新前刪、更新後延遲再刪)。
get_hits / (get_hits + get_misses) → 命中率 (目標 > 90%)evictions → 驅逐次數 (持續增長說明內存不足)bytes / limit_maxbytes → 內存利用率curr_connections → 連接數健康度