Memcache 是高效能分散式記憶體快取系統,PHP Memcache 擴展提供物件導向介面。本文涵蓋連線、增刪改查、統計資訊、進階模式(快取穿透/擊穿/雪崩防護)完整實戰範例。
<?php
// 基本連線與操作
$mem = new Memcache();
$mem->connect('127.0.0.1', 11211) or die("連線失敗");
// 1. 新增(不存在才寫入)
$mem->add('user:1:name', 'Alice', 0, 3600); // key, value, flag, expire(秒)
$mem->add('user:1:age', 25, 0, 3600);
// 2. 設定(覆蓋寫入)
$mem->set('user:1:city', 'Taipei', 0, 3600);
// 3. 取得單一
$name = $mem->get('user:1:name');
echo "Name: $name\n";
// 4. 批次取得
$keys = ['user:1:name', 'user:1:age', 'user:1:city'];
$vals = $mem->get($keys);
print_r($vals); // ['user:1:name'=>'Alice', 'user:1:age'=>25, ...]
// 5. 替換(存在才更新)
$mem->replace('user:1:name', 'Alice Chen', 0, 3600);
// 6. 刪除
$mem->delete('user:1:age');
// 7. 統計資訊
print_r($mem->getStats()); // 伺服器統計
print_r($mem->getExtendedStats()); // 詳細統計(含 slab 資訊)
$mem->close();
?>
<?php
// pm25_cache.php
$mem = new Memcache();
$mem->connect('127.0.0.1', 11211);
$city = $_GET['city'] ?? 'Taipei';
$cacheKey = "pm25:$city";
$expire = 300; // 5 分鐘
// 1. 嘗試從快取取得
$cached = $mem->get($cacheKey);
if ($cached !== false) {
echo json_encode(['source' => 'cache', 'data' => $cached]);
exit;
}
// 2. 快取未命中 → 查資料庫
// 模擬 DB 查詢
$dbData = queryPm25FromDb($city); // 你的 DB 查詢函式
if ($dbData) {
// 3. 寫入快取(防止快取穿透:即使查無資料也快取空值,短期)
$mem->set($cacheKey, $dbData, 0, $expire);
echo json_encode(['source' => 'db', 'data' => $dbData]);
} else {
// 查無資料:快取空陣列 1 分鐘,防止穿透
$mem->set($cacheKey, [], 0, 60);
echo json_encode(['source' => 'db', 'data' => []]);
}
function queryPm25FromDb($city) {
// 實際對接 PDO/MySQLi
// return $pdo->query("SELECT * FROM pm25 WHERE city='$city'")->fetch();
return ['city' => $city, 'pm25' => rand(10, 150), 'time' => date('H:i:s')];
}
?>
<?php
function getWithMutex($mem, $key, $expire, $dbCallback) {
$value = $mem->get($key);
if ($value !== false) return $value;
// 取得分散式鎖(利用 add 原子性)
$lockKey = "$key:lock";
$lockExpire = 10; // 鎖最多持有 10 秒
if ($mem->add($lockKey, 1, 0, $lockExpire)) {
// 獲得鎖:查 DB 並寫入快取
$value = $dbCallback();
$mem->set($key, $value, 0, $expire);
$mem->delete($lockKey); // 釋放鎖
return $value;
} else {
// 未獲鎖:短暫睡眠重試(或直接回傳舊資料)
usleep(50000); // 50ms
return $mem->get($key) ?: $dbCallback(); // 兜底
}
}
// 使用
$data = getWithMutex($mem, "hot:key", 300, function() {
return queryDb();
});
?>
$expire = 300 + rand(0, 60) 錯開過期時間。| 特性 | Memcache (舊) | Memcached (新,推薦) |
|---|---|---|
| 類別名 | Memcache | Memcached |
| 支援二進位協議 | 否 | 是 |
| 支援 SASL 認證 | 否 | 是 |
| 支援觸發回呼 | 否 | 是 |
| 效能 | 一般 | 較好 |
| 維護狀態 | 低 | 活躍 |
建議: 新專案一律使用 Memcached 擴展,API 相似但功能更完整。
md5($longKey))。gzcompress() 或拆分。get 時會回傳,應用層自行處理。$mem->pconnect() 或連線池,避免頻繁建立 TCP 連線。$stats = $mem->getStats();
echo "命中率: " . ($stats['get_hits'] / ($stats['get_hits'] + $stats['get_misses']) * 100) . "%\n";
echo "記憶體使用: " . ($stats['bytes'] / 1024 / 1024) . " MB\n";
echo "連線數: " . $stats['curr_connections'] . "\n";
echo "項目數: " . $stats['curr_items'] . "\n";
Memcache 核心操作極簡單:add/set/get/delete/replace。實戰關鍵在於 快取策略設計:合理設定過期時間、防穿透/擊穿/雪崩、監控命中率。新專案請改用 Memcached 擴展 或 Redis(功能更豐富、支援資料結構、持久化),Memcache 適合純 Key-Value、極高讀寫、無持久化需求的場景。