Memcached 是高效能分散式記憶體快取系統,ThinkPHP 透過快取驅動機制原生支援。本文涵蓋 Windows/Linux 安裝部署、ThinkPHP 3.x/5.x/6.x/8.x 配置差異、自定義驅動擴展、叢集部署、序列化選擇、監控指標與常見坑,助你快速落地生產級快取層。
# CentOS/RHEL
yum install -y memcached libmemcached
systemctl enable memcached --now
# Ubuntu/Debian
apt update && apt install -y memcached
systemctl enable memcached --now
# 配置檔 /etc/sysconfig/memcached (CentOS) 或 /etc/memcached.conf (Ubuntu)
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="512" # MB,根據記憶體調整
OPTIONS="-l 127.0.0.1" # 僅本地回環,安全起見;叢集需綁定內網 IP
# 重啟生效
systemctl restart memcached
# 驗證
echo "stats" | nc 127.0.0.1 11211
memcached-win64.zip (GitHub: memcached/memcached releases)D:\memcached\D:\memcached\memcached.exe -d installD:\memcached\memcached.exe -d start (或 net start memcached)# Linux (PHP 8.1+)
pecl install memcached
# 或 yum install php-pecl-memcached / apt install php8.1-memcached
# Windows
# 1. 下載對應 PHP 版本/TS/NTS 的 php_memcached.dll
# 2. 放入 ext/ 目錄
# 3. php.ini 添加: extension=memcached
# 4. 重啟 php-fpm / Apache
# 驗證
php -m | grep memcached
php -r "new Memcached(); echo 'OK';"
關鍵區別:memcache (舊、無維護、不支援叢集) vs memcached (基於 libmemcached、支援一致性哈希、二進制協議、SASL 認證) — 務必安裝 memcached 擴展。
<?php
// Conf/config.php
return [
'DATA_CACHE_TYPE' => 'Memcache', // 驅動名稱 (ThinkPHP 3.x 內建驅動名為 Memcache)
'DATA_CACHE_TIME' => 3600, // 預設快取秒數
'DATA_CACHE_PREFIX' => 'tp_', // 鍵前綴
'DATA_CACHE_CONFIG' => [
'host' => '127.0.0.1',
'port' => 11211,
'persistent' => true, // 長連接
'timeout' => 2,
'retry_interval' => 100,
],
];
<?php
// config/cache.php
return [
'default' => 'memcached',
'stores' => [
'memcached' => [
'type' => 'memcached',
'servers' => [
['127.0.0.1', 11211, 100], // host, port, weight
// ['10.0.0.2', 11211, 50], // 叢集新增節點
],
'options' => [
\Memcached::OPT_COMPRESSION => true, // 自動壓縮大值
\Memcached::OPT_SERIALIZER => \Memcached::SERIALIZER_IGBINARY, // 高效序列化
\Memcached::OPT_BINARY_PROTOCOL => true, // 二進制協議
\Memcached::OPT_TCP_NODELAY => true,
\Memcached::OPT_NO_BLOCK => true,
\Memcached::OPT_CONNECT_TIMEOUT => 2000, // ms
\Memcached::OPT_RETRY_TIMEOUT => 1,
],
'prefix' => 'tp5_',
'expire' => 3600,
],
],
];
<?php
// config/cache.php
return [
'default' => 'memcached',
'stores' => [
'memcached' => [
'type' => 'memcached',
'servers' => [
['host' => '127.0.0.1', 'port' => 11211, 'weight' => 100],
],
'options' => [
\Memcached::OPT_COMPRESSION => true,
\Memcached::OPT_SERIALIZER => \Memcached::SERIALIZER_IGBINARY,
\Memcached::OPT_BINARY_PROTOCOL => true,
],
'prefix' => 'tp6_',
'expire' => 3600,
],
],
];
<?php
// ThinkPHP 5/6/8 門面
use think\facade\Cache;
// 基礎操作
Cache::set('key', 'value', 600); // 寫入,10 分鐘過期
Cache::get('key'); // 讀取
Cache::has('key'); // 存在性檢查
Cache::delete('key'); // 刪除
Cache::clear(); // 清空當前存儲 (謹慎)
// 進階操作
Cache::remember('heavy_compute', 3600, function() {
return User::with('posts')->get(); // 緩存未命中時執行閉包並存入
});
Cache::inc('counter'); // 原子遞增 (需 Memcached 驅動支援)
Cache::dec('counter'); // 原子遞減
// 多鍵批量
Cache::pull(['key1', 'key2']); // 讀取並刪除
Cache::setMultiple(['a'=>1, 'b'=>2], 600); // 批量寫入
// 標籤緩存 (需驅動支援,Memcached 原生不支援,需額外實現)
// Cache::tag('user')->set('profile_1', $data);
| 序列化器 | 速度 | 體積 | 特性 | 安裝 |
|---|---|---|---|---|
| igbinary | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | 二進制、支援 PHP 所有類型、需編譯擴展 | pecl install igbinary |
| msgpack | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 跨語言、極小體積、需 msgpack 擴展 | pecl install msgpack |
| php (原生) | ⭐⭐ | ⭐⭐ | 無依賴、體積大、慢、不支援資源/閉包 | 內建 |
建議:生產環境強制啟用 igbinary,需確保所有 PHP 節點安裝相同版本。
// 只壓縮超過閾值的值 (預設 100 bytes 以上)
\Memcached::OPT_COMPRESSION => true,
\Memcached::OPT_COMPRESSION_THRESHOLD => 2000, // 2KB 以上才壓縮
\Memcached::OPT_COMPRESSION_TYPE => \Memcached::COMPRESSION_LZ4, // 或 ZSTD (需 libmemcached 1.0.18+)
Memcached 客戶端內建 Ketama 一致性哈希算法,自動根據權重分配鍵。新增/移除節點只影響少部分鍵,但需注意:
# 獲取統計
echo "stats" | nc 127.0.0.1 11211
# 關鍵指標解讀
get_hits / (get_hits + get_misses) = 命中率 (目標 > 95%)
bytes / limit_maxbytes = 記憶體使用率 (目標 < 80%)
evictions > 0 表示發生驅逐 (LRU),需擴容或調整 TTL
curr_connections 連接數 (監控連接洩漏)
threads 執行緒數 (通常 4-8)
expire + rand(0, 300)) + 多級快取 (本地記憶體 + Memcached)。<?php
// extend/cache/driver/MemcachedExtended.php
namespace extend\cache\driver;
use think\cache\Driver;
class MemcachedExtended extends Driver {
protected \Memcached $handler;
protected array $options = [];
protected function init(array $config): void {
$this->handler = new \Memcached();
// ... 連接配置同前
$this->options = $config;
}
// 重寫 get 方法:支援「獲取並延長過期時間」
public function get($name, $default = false) {
$key = $this->getCacheKey($name);
// 使用 getDelayed + fetchAll 實現單次網路往返獲取多鍵
// 這裡簡化演示
$value = $this->handler->get($key);
if ($value !== false) {
// 選項:讀取時自動續期 (LRU 友好)
if ($this->options['auto_extend'] ?? false) {
$this->handler->touch($key, $this->options['expire'] ?? 3600);
}
return $value;
}
return $default;
}
// 新增方法:獲取鍵剩餘 TTL
public function getTtl($name): int {
$key = $this->getCacheKey($name);
return $this->handler->get($key, null, \Memcached::GET_EXTENDED)['ttl'] ?? 0;
}
}
配置使用:'type' => '\\extend\\cache\\driver\\MemcachedExtended'
| 現象 | 原因 | 解決 |
|---|---|---|
| Cache::get() 返回 false 但鍵存在 | 序列化器不一致 (寫入 igbinary,讀取 php) | 統一所有節點 OPT_SERIALIZER 配置 |
| 新增節點後命中率暴跌 | 客戶端伺服器列表順序不一致 | 配置管理下發統一列表,或使用一致性哈希代理 (twemproxy) |
| 大值寫入失敗 (SERVER_ERROR) | 超過 Memcached 預設 1MB 限制 | 啟用壓縮、拆分大物件、或調整 -I 啟動參數 (如 -I 4m) |
| PHP-FPM 重啟後連接失效 | 持久連接在重啟後變 stale | 啟用 OPT_NO_BLOCK + 重試邏輯,或改用短連接 |
| SASL 認證失敗 | libmemcached 編譯未啟用 SASL | 重新編譯安裝 --enable-sasl,或使用 VPN/安全組隔離 |
隨著業務增長,Redis 提供更豐富資料結構 (Hash/List/Set/SortedSet/Stream)、持久化、發布訂閱、Lua 腳本、原生叢集。遷移路徑:
ThinkPHP 整合 Memcached 核心在於:正確安裝 memcached (非 memcache) 擴展、統一 igbinary 序列化、啟用壓縮與二進制協議、配置一致性哈希叢集、建立監控告警體系。掌握這些工程細節,即可構建高可用、高效能的分散式快取層,支撐百萬級 QPS 訪問量。