在大型網站架構中,常見的做法是利用 Memcached 當作記憶體級緩存層,搭配 MySQL 主從複製實現讀寫分離與資料備份。這樣的架構能顯著提升讀取效能,同時保障資料安全。本文將透過 PHP 代碼範例,示範如何整合 Memcached 叢集與 MySQL 主從環境,實現靈活的資料存取策略。
首先定義伺服器連線資訊,包含多台 Memcached 節點與 MySQL 主從伺服器:
<?php
// Memcached 叢集配置,鍵名作為邏輯分組標識
$memcached = array(
'cn' => array('192.168.254.144', 11211),
'en' => array('192.168.254.144', 11212)
);
// MySQL 主從配置
$mysql = array(
'master' => array('192.168.254.213', 'root', '1', 'mydz'),
'slave_1' => array('192.168.254.144', 'root', '1', 'mydz')
// 可擴展多台從庫
);
?>
封裝支援持久連線、多伺服器路由(透過鍵名前綴決定存放節點)的基本操作:
<?php
class Memcached {
private $mem;
public $pflag = ''; // 'p' 表示使用 pconnect
private function memConnect($serkey) {
global $memcached;
$this->mem = new Memcache;
$link = $this->pflag ? 'pconnect' : 'connect';
$server = $memcached[$serkey];
$this->mem->$link($server[0], $server[1]) or die('Memcached 連線失敗');
}
public function set($ser_key, $values, $flag = '', $expire = '') {
$this->memConnect($this->tag($ser_key));
return $this->mem->set($ser_key, $values, $flag, $expire);
}
public function get($ser_key) {
$this->memConnect($this->tag($ser_key));
return $this->mem->get($ser_key) ?: false;
}
// 依鍵名前綴(如 'cn_'、'en_')決定目標伺服器
private function tag($ser_key) {
return explode('_', $ser_key)[0];
}
}
?>
設計亮點:採用手動指定節點(鍵名前綴)而非一致性哈希,適合業務邏輯明確的場景,便於資料分片管理。
實現寫主讀從,從庫採用 Session 輪詢負載均衡:
<?php
class Mysql {
private $mysqlmaster;
private $mysqlslave;
public function __construct() {
global $mysql;
$this->mysqlmaster = new mysqli(
$mysql['master'][0], $mysql['master'][1], $mysql['master'][2], $mysql['master'][3]
);
$this->mysqlslave = $this->autoSelectSlave($mysql);
if (mysqli_connect_errno()) {
die("連線失敗: " . mysqli_connect_error());
}
$this->mysqlmaster->set_charset("utf8mb4");
$this->mysqlslave->set_charset("utf8mb4");
}
private function autoSelectSlave($mysql) {
session_start();
$_SESSION['SID'] = ($_SESSION['SID'] ?? 0) + 1;
if ($_SESSION['SID'] >= count($mysql)) $_SESSION['SID'] = 1;
$key = 'slave_' . $_SESSION['SID'];
return new mysqli($mysql[$key][0], $mysql[$key][1], $mysql[$key][2], $mysql[$key][3]);
}
// 寫操作走主庫
public function mquery($sql) {
return $this->mysqlmaster->query($sql);
}
// 讀操作走從庫
public function squery($sql) {
return $this->mysqlslave->query($sql);
}
public function fetArray($sql) {
$result = $this->squery($sql);
$rows = [];
while ($row = $result->fetch_assoc()) $rows[] = $row;
return $rows;
}
}
?>
<?php
require 'init.php'; // 載入上述類與配置
$mem = new Memcached();
$sq = new Mysql();
$sql = "INSERT INTO mybb(pid) VALUES(200)";
$cacheKey = 'cn_' . md5($sql); // 緩存鍵綁定 cn 節點
// 1. 嘗試從緩存讀取
if (!$result = $mem->get($cacheKey)) {
// 2. 緩存未命中:寫入主庫
$sq->mquery($sql);
// 3. 從從庫讀取最新資料
$result = $sq->fetArray("SELECT * FROM mybb");
// 4. 寫入緩存
$mem->set($cacheKey, $result);
}
// 5. 輸出結果
foreach ($result as $var) {
echo $var['pid'] . "<br>";
}
?>
文末附帶的 DBManagement 類提供了完整的資料庫結構與資料導入導出功能,支援:
Install.sql)SELECT ... INTO OUTFILE 與 LOAD DATA INFILE)核心方法包括 BackupDatabase()、RestoreDatabase()、ExportData()、ImportData() 等,適合作為維護腳本或管理後台的備份模組。
本方案展示了「Memcached 緩存層 + MySQL 主從讀寫分離」的經典落地實踐。關鍵點在於:
實際生產環境建議進一步引入連線池、異步刷新、緩存穿透/雪崩防護等機制。