ThinkPHP 內建 Cache 類支援多種驅動,但預設 CacheMemcache 僅支援單一伺服器。本文示範如何修改驅動類支援多台 Memcache 伺服器分散式部署,並附上監控與告警範例。
<?php
// 原始 CacheMemcache.class.php 片段
if (empty($options)) {
$options = ['host'=>'127.0.0.1', 'port'=>11211, 'timeout'=>false, 'persistent'=>false];
}
$func = $options['persistent'] ? 'pconnect' : 'connect';
$this->handler = new Memcache;
$this->connected = $options['timeout'] === false
? $this->handler->$func($options['host'], $options['port'])
: $this->handler->$func($options['host'], $options['port'], $options['timeout']);
?>
僅支援單一 host/port,無法利用 Memcache 原生分散式一致性雜湊。
<?php
// 修改後的 connect 邏輯
if (empty($options)) {
$options = [
'timeout' => false,
'persistent' => false,
'servers' => [
['ip' => '127.0.0.1', 'port' => 11211],
['ip' => '127.0.0.1', 'port' => 11212],
['ip' => '192.168.1.100', 'port' => 11211],
],
];
}
$func = 'addServer'; // 統一使用 addServer 建立連線池
$this->handler = new Memcache;
if ($options['timeout'] === false) {
foreach ($options['servers'] as $server) {
$this->handler->$func($server['ip'], $server['port']);
}
$this->connected = true;
} else {
// 帶 timeout 連線需逐台嘗試
foreach ($options['servers'] as $server) {
$this->handler->$func($server['ip'], $server['port'], $options['timeout']);
}
$this->connected = true;
}
?>
<?php
return [
'DATA_CACHE_TYPE' => 'Memcache',
'MEMCACHE_CONFIG' => [
'servers' => [
['ip' => '10.0.0.1', 'port' => 11211],
['ip' => '10.0.0.2', 'port' => 11211],
['ip' => '10.0.0.3', 'port' => 11211],
],
'persistent' => true,
'timeout' => 1,
],
];
?>
撰寫簡單測試腳本,寫入大量鍵值並觀察各 Memcache 節點的 stats items、stats slabs,確認資料依一致性雜湊分散於各節點。
<?php
// 定期執行的監控腳本 (cron 每分鐘)
$servers = [
['ip'=>'10.0.0.1', 'port'=>11211],
['ip'=>'10.0.0.2', 'port'=>11211],
];
foreach ($servers as $s) {
$mc = new Memcache;
$connected = @$mc->connect($s['ip'], $s['port'], 1);
if (!$connected) {
// 發送郵件告警 (需引入 PHPMailer)
mail('admin@example.com', 'Memcache 節點離線', "節點 {$s['ip']}:{$s['port']} 無法連線");
}
}
?>
memcache 擴充套件(非 memcached)。servers 陣列順序必須一致,確保一致性雜湊結果相同。