萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

Memcached 搭配 MySQL 主從架構實現高效備份與讀寫分離

前言

在大型網站架構中,常見的做法是利用 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')
    // 可擴展多台從庫
);
?>

Memcached 封裝類

封裝支援持久連線、多伺服器路由(透過鍵名前綴決定存放節點)的基本操作:

<?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];
    }
}
?>

設計亮點:採用手動指定節點(鍵名前綴)而非一致性哈希,適合業務邏輯明確的場景,便於資料分片管理。

MySQL 主從封裝類

實現寫主讀從,從庫採用 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 主從讀寫分離」的經典落地實踐。關鍵點在於:

  1. 配置集中化,便於主從切換與擴展
  2. Memcached 以業務前綴路由,避免熱點與單點
  3. MySQL 封裝層自動路由讀寫,業務代碼無感知
  4. 緩存策略採用「寫入後更新緩存」,保證最終一致性

實際生產環境建議進一步引入連線池、異步刷新、緩存穿透/雪崩防護等機制。

copyright © 萬盛學電腦網 all rights reserved