首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 整合 Memcached 與 MySQL 主從架構開發實戰

     編輯:PHP 相關知識

架構概覽

本文展示一個完整的 PHP 應用架構:Memcached 叢集(多實例模擬多台)搭配 MySQL 主從複寫(寫入 Master、讀取 Slave),並透過一致性雜湊(以鍵名前綴分叢集)分配快取節點。程式碼包含連線管理、查詢分離、快取策略與設定檔範例。

Memcached 類別封裝

class Memcached {
    private $mem;
    public $pflag = ''; // 是否使用持久連線

    private function memConnect($serkey) {
        require 'config.php';
        $server = $memcached;
        $this->mem = new Memcache;
        $link = !$this->pflag ? 'connect' : 'pconnect';
        $this->mem->$link($server[$serkey][0], $server[$serkey][1]) or $this->errordie('memcached connect error');
    }

    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_xxx → cn 叢集)
    private function tag($ser_key) {
        return explode('_', $ser_key)[0];
    }

    private function errordie($errmsg) { die($errmsg); }
}

MySQL 主從類別封裝

class Mysql {
    private $mysqlmaster;
    private $mysqlslave;
    private static $auid = 0;

    public function __construct() {
        require 'config.php';
        $msg = $mysql;
        $this->mysqlmaster = new mysqli($msg['master'][0], $msg['master'][1], $msg['master'][2], $msg['master'][3]);
        $this->mysqlslave = $this->autotranscat($msg); // 輪詢 Slave
        if(mysqli_connect_errno()) exit("Connect failed: " . mysqli_connect_error());
        $this->mysqlmaster->set_charset("latin1");
        $this->mysqlslave->set_charset("latin1");
    }

    // Session 輪詢選擇 Slave
    private function autotranscat($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) {
        if($result = $this->squery($sql)) {
            while($row = $result->fetch_array(MYSQLI_ASSOC)) $resultraa[] = $row;
            return $resultraa;
        }
        return false;
    }
}

設定檔範例 (config.php)

 array('192.168.254.144', 11211),
    'en' => array('192.168.254.144', 11212)
);

$mysql = array(
    'master' => array('192.168.254.213', 'root', '1', 'mydz'),
    'slave_1' => array('192.168.254.144', 'root', '1', 'mydz')
);
?>

業務邏輯範例:寫入穿透 + 快取旁路

require 'init.php';
$mem = new Memcached;
$sq = new Mysql;

$sql = "insert into mybb(pid) values(200)";
$mdsql = md5($sql); // SQL 雜湊作為快取鍵一部分

// 快取未命中 → 寫入 Master → 從 Slave 讀取最新資料 → 存入快取
if(!$result = $mem->get('cn_' . $mdsql)) {
    $sq->mquery($sql); // 寫入主庫
    $result = $sq->fetArray("select * from mybb"); // 從從庫讀取
    foreach($result as $var) echo $var['pid'];
    $mem->set('cn_' . $mdsql, $result); // 存入 cn 叢集
} else {
    foreach($result as $var) echo $var['pid']; // 快取命中直接輸出
}

Memcached 內部運作補充

  • 啟動流程:settings_init → 解析參數 → daemon() 建立守護進程 → 初始化 slab/hash/event → 進入 drive_machine 事件循環
  • 協定:自訂文字協定,換行符統一為 \r\n,支援 get/set/add/replace/incr/decr/stats 等指令
  • 記憶體管理:Slab Allocator 預先分塊,避免碎片,支援 LRU 淘汰

生產環境建議

  1. 使用 Memcached::addServer 建立連線池,而非單一連線
  2. 鍵名設計加入版本號/業務前綴,避免衝突
  3. 快取失效策略:TTL + 主動失效(寫入時 delete 對應鍵)
  4. MySQL 讀寫分離建議使用 ProxySQL 或中介軟體,而非 Session 輪詢
  5. 監控指標:命中率、回收率、連線數、延遲
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved