PHP Memcached 擴展完整使用指南:安裝、基本操作與進階技巧
Memcached 是高效能分散式記憶體快取系統,廣泛用於減輕資料庫負載、加速頁面回應。本文詳細說明 PHP memcache 擴展的安裝設定、核心 API 操作、資料類型支援與實務注意事項。
環境安裝與設定
1. 安裝擴展 (Linux 範例)
# Ubuntu/Debian
sudo apt-get install php-memcache memcached
# CentOS/RHEL
sudo yum install php-pecl-memcache memcached
# 編譯安裝 (需 phpize)
wget https://pecl.php.net/get/memcache-4.0.5.2.tgz
tar -xzf memcache-4.0.5.2.tgz
cd memcache-4.0.5.2
phpize
./configure --enable-memcache
make && sudo make install
2. php.ini 設定
extension=memcache.so
; 連線設定
memcache.allow_failover = 1
memcache.max_failover_attempts = 20
memcache.chunk_size = 8192
memcache.default_port = 11211
; Session 儲存至 Memcached (可選)
; session.save_handler = memcache
; session.save_path = "tcp://127.0.0.1:11211?persistent=1&weight=1&timeout=1&retry_interval=15"
3. 啟動 Memcached 服務
# 前景執行 (測試用)
memcached -u nobody -m 64 -p 11211 -c 1024
# 背景執行 (生產環境)
memcached -d -u nobody -m 512 -p 11211 -c 2048 -P /var/run/memcached.pid
核心 API 操作完整範例
<?php
// 建立連線
$mem = new Memcache();
$connected = $mem->connect('127.0.0.1', 11211); // 或 addServer 多台
if (!$connected) {
die('Memcached 連線失敗');
}
// 多伺服器叢集 (推薦生產環境)
$mem->addServer('192.168.1.10', 11211, true, 1); // weight=1
$mem->addServer('192.168.1.11', 11211, true, 2); // weight=2 (較多連線)
// ===== 基本 CRUD =====
$key = 'user:1001';
// 寫入 (set: 新增或覆蓋)
$userData = ['id'=>1001, 'name'=>'張三', 'email'=>'zhang@example.com'];
$mem->set($key, $userData, MEMCACHE_COMPRESSED, 3600); // 過期 1 小時
// 讀取
$cached = $mem->get($key);
var_dump($cached);
// 僅在不存在時寫入 (add)
$mem->add('config:site_name', 'My Website', 0, 86400); // 永不過期
// 替換既有值 (replace)
$mem->replace($key, array_merge($userData, ['last_login'=>time()]), MEMCACHE_COMPRESSED, 3600);
// 刪除
$mem->delete($key);
// 批次刪除 (需 1.6+)
$mem->delete('prefix_*'); // 不支援通配符,需自行維護鍵列表
// ===== 計數器操作 (原子性) =====
$mem->set('counter:pageviews', 0);
$mem->increment('counter:pageviews'); // 1
$mem->increment('counter:pageviews', 5); // 6
$mem->decrement('counter:pageviews', 2); // 4
// ===== 狀態監控 =====
$stats = $mem->getStats();
$extended = $mem->getExtendedStats();
print_r($stats); // 包含版本、連線數、命中率、記憶體用量等
// ===== 關閉連線 =====
$mem->close();
?>
支援的資料類型與序列化
| 類型 | 支援 | 說明 |
| 字串 | ✅ 完美 | 直接儲存 |
| 整數/浮點數 | ✅ 完美 | 直接儲存,計數器需整數 |
| 布林值 | ✅ 完美 | 直接儲存 |
| 陣列 | ✅ 自動序列化 | 內部使用 PHP serialize() |
| 物件 | ✅ 自動序列化 | 需類別定義存在於反序列化時 |
| NULL | ✅ 支援 | 可區分「不存在」與「值為 NULL」 |
| 資源 | ❌ 不支援 | 資料庫連線、檔案控制代碼等無法儲存 |
序列化策略選擇
<?php
// 預設使用 PHP serialize (支援物件、資源引用等)
// 適用:複雜物件、需保持類別型別
// 替代方案:JSON (跨語言、可讀、略快)
$mem->set('key', json_encode($data), 0, 3600);
$data = json_decode($mem->get('key'), true); // true = 關聯陣列
// 替代方案:igbinary (更快、更小、支援 PHP 7+)
// 需安裝 igbinary 擴展並設定
ini_set('memcache.serializer', 'igbinary');
分散式架構關鍵概念
- 一致性雜湊:Client 端根據 Key 計算哈希值,決定存哪台 Server,非隨機分配
- 無中心協調:各 Server 互不通訊,Client 獨立決定路由
- 動態增減節點:
addServer() 只是加入連線池,實際連線在首次操作時建立 (Lazy Connect)
- 故障轉移:
allow_failover=1 時,寫入失敗自動嘗試下一台
實務最佳實踐
Key 命名規範
// 格式:業務域:實體類型:ID:屬性(可選)
// 範例
'user:profile:1001'
'user:permissions:1001'
'article:content:5001'
'article:comments:5001:page:1'
'config:site:settings'
'counter:pageviews:homepage'
快取策略模式
<?php
// Cache-Aside Pattern (旁路快取) - 最常用
function getUserProfile($uid) {
global $mem;
$key = "user:profile:{$uid}";
// 1. 先查快取
if ($data = $mem->get($key)) {
return $data; // Hit
}
// 2. Miss: 查資料庫
$data = $db->fetch_one("SELECT * FROM users WHERE id = {$uid}");
if (!$data) return false;
// 3. 寫入快取 (設定過期時間 + 隨機抖動防雪崩)
$ttl = 3600 + rand(0, 300);
$mem->set($key, $data, 0, $ttl);
return $data;
}
// 更新時雙寫或失效
function updateUserProfile($uid, $newData) {
global $mem, $db;
$db->update('users', $newData, "id = {$uid}");
$mem->delete("user:profile:{$uid}"); // 失效策略
// 或 $mem->set("user:profile:{$uid}", $mergedData, 0, 3600); // 更新策略
}
防止快取穿透/雪崩/擊穿
| 問題 | 現象 | 解決方案 |
| 快取穿透 | 查詢不存在的 Key,每次都穿透到 DB | 快取空值 (set key=null, ttl=短);布隆過濾器攔截 |
| 快取雪崩 | 大量 Key 同時間過期,請求湧入 DB | TTL 加隨機抖動;多級快取;熔斷降級 |
| 快取擊穿 | 熱點 Key 過期瞬間,大量並發查 DB | 互斥鎖 (setnx) 重建;熱點資料永不過期 |
常見問題排查
- 連線失敗:檢查防火牆、SELinux、memcached.conf 綁定 IP (預設 127.0.0.1)
- 資料莫名消失:記憶體不足觸發 LRU 淘汰;檢查
stats evictions
- 命中率低:分析存取模式,調整 TTL、Key 粒度、預熱策略
- PHP 7+ 相容性:舊版 memcache 擴展不支援 PHP 7,需用
memcached (有 d) 擴展或 igbinary
memcache vs memcached 擴展比較
| 特性 | memcache (舊) | memcached (新,推薦) |
| PHP 7/8 支援 | ❌ 無官方支援 | ✅ 完整支援 |
| 二進制協議 | ❌ | ✅ |
| SASL 認證 | ❌ | ✅ |
| 多鍵獲取 (getMulti) | ❌ | ✅ |
| 觸發式回調 | ❌ | ✅ |
| 序列化器選擇 | 固定 PHP serialize | igbinary, msgpack, json, php |
建議: 新專案務必使用 memcached (有 d) 擴展,功能更完整、效能更好、長期維護有保障。