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

PHP Memcache 完整指南:安裝、核心 API、分佈式架構、安全加固與實戰封裝

     編輯:PHP 相關知識

名詞釐清

  • Memcache:專案名稱 / PHP 擴展名稱(php-memcache)
  • memcached:服務端守護進程二進制檔(/usr/bin/memcached)
  • Memcached (PHP extension):較新、功能更全的 PHP 擴展(php-memcached,基於 libmemcached)

本文針對 php-memcache(舊版擴展),新專案建議改用 php-memcached 或 Redis。

安裝部署

服務端

# Ubuntu/Debian
sudo apt install memcached
# 配置 /etc/memcached.conf
# -m 1024        # 1GB 記憶體
# -p 11211       # 埠
# -l 127.0.0.1   # 僅本地回環(安全)
# -u memcache    # 低權限用戶
sudo systemctl restart memcached

PHP 擴展

# Ubuntu PHP 8.2
sudo apt install php8.2-memcache
sudo systemctl restart php8.2-fpm

核心 API 速查(Memcache 類)

方法用途關鍵參數
connect(host, port)短連線timeout(秒)
pconnect(host, port)持久連線(跨請求復用)timeout
addServer(host, port, ...)加入伺服器池(延遲連線)persistent, weight, timeout, retry_interval, status, failure_callback
set(key, var, flag, expire)儲存(存在則覆蓋)flag: MEMCACHE_COMPRESSED, expire: 秒/Unix時間戳
add(key, var, flag, expire)儲存(不存在才寫入)同 set
replace(key, var, flag, expire)覆蓋(必須存在)同 set
get(key/keys[])讀取單鍵/多鍵返回值/關聯陣列
delete(key, timeout)刪除(可延遲)timeout: 秒後真正刪除
increment/decrement(key, value)原子增減返回新值
flush()標記所有項過期(不釋放記憶體)無參數
getStats()統計資訊type: slabs, items, sizes...
getVersion()版本號字串
close()關閉短連線持久連線不受影響
setCompressThreshold(size, ratio)大值自動壓縮預設 20KB, 0.2

實戰封裝:支援叢集、鍵前綴、序列化、異常處理

<?php
declare(strict_types=1);

class MemcacheManager {
    private \Memcache $mc;
    private string $prefix = '';
    private int $defaultTtl = 3600;

    public function __construct(array $servers, string $prefix = '', array $options = []) {
        $this->prefix = $prefix;
        $this->defaultTtl = $options['default_ttl'] ?? 3600;

        $this->mc = new \Memcache();
        foreach ($servers as $srv) {
            $this->mc->addServer(
                $srv['host'],
                $srv['port'] ?? 11211,
                $srv['persistent'] ?? true,
                $srv['weight'] ?? 1,
                $srv['timeout'] ?? 1,
                $srv['retry_interval'] ?? 15,
                $srv['status'] ?? true,
                $srv['failure_callback'] ?? null
            );
        }

        // 可選:設定壓縮閾值
        if (isset($options['compress_threshold'])) {
            $this->mc->setCompressThreshold($options['compress_threshold'][0], $options['compress_threshold'][1] ?? 0.2);
        }
    }

    private function key(string $key): string {
        return $this->prefix . $key;
    }

    public function set(string $key, mixed $value, int $ttl = 0): bool {
        return $this->mc->set($this->key($key), $value, 0, $ttl ?: $this->defaultTtl);
    }

    public function get(string $key, mixed &$flags = null): mixed {
        return $this->mc->get($this->key($key), $flags);
    }

    public function getMulti(array $keys): array {
        $prefixed = array_map([$this, 'key'], $keys);
        return $this->mc->get($prefixed);
    }

    public function add(string $key, mixed $value, int $ttl = 0): bool {
        return $this->mc->add($this->key($key), $value, 0, $ttl ?: $this->defaultTtl);
    }

    public function replace(string $key, mixed $value, int $ttl = 0): bool {
        return $this->mc->replace($this->key($key), $value, 0, $ttl ?: $this->defaultTtl);
    }

    public function delete(string $key): bool {
        return $this->mc->delete($this->key($key));
    }

    public function increment(string $key, int $offset = 1): int|false {
        return $this->mc->increment($this->key($key), $offset);
    }

    public function decrement(string $key, int $offset = 1): int|false {
        return $this->mc->decrement($this->key($key), $offset);
    }

    public function flush(): bool {
        return $this->mc->flush();
    }

    public function getStats(): array|false {
        return $this->mc->getStats();
    }
}

// 使用示例
$mem = new MemcacheManager(
    [
        ['host' => '10.0.1.10', 'weight' => 2],
        ['host' => '10.0.1.11', 'weight' => 1],
    ],
    'myapp:',
    ['default_ttl' => 1800, 'compress_threshold' => [50000, 0.3]]
);

$mem->set('user:1001', ['name' => 'John', 'vip' => true], 3600);
$data = $mem->get('user:1001');
$mem->increment('counter:pageview');
$mem->delete('temp:token:xyz');

分佈式架構:一致性雜湊與鍵路由

Memcache 客戶端內建一致性雜湊(addServer 時指定 weight),自動將鍵分散至多節點。進階路由策略:

  • 業務分片: user:{uid}:profile → 依 uid % N 固定節點,利於批量操作。
  • 標籤分組: tag:article:123、tag:user:456 → 同標籤鍵路由至同節點,支援 flush_by_tag(需自建索引)。
  • 熱鍵隔離: 高頻計數器單獨節點,避免擠佔業務記憶體。

減輕資料庫壓力:緩存旁路模式

<?php
function getUserProfile(int $uid, PDO $pdo, MemcacheManager $mc): array {
    $key = "user:profile:{$uid}";
    if ($data = $mc->get($key)) return $data;

    $stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
    $stmt->execute([$uid]);
    $data = $stmt->fetch(PDO::FETCH_ASSOC) ?: [];

    if ($data) $mc->set($key, $data, 3600); // 1 小時
    return $data;
}

function updateUserProfile(int $uid, array $fields, PDO $pdo, MemcacheManager $mc): bool {
    $set = implode(', ', array_map(fn($k) => "$k = :$k", array_keys($fields)));
    $sql = "UPDATE users SET $set WHERE id = :uid";
    $fields['uid'] = $uid;
    $ok = $pdo->prepare($sql)->execute($fields);

    if ($ok) $mc->delete("user:profile:{$uid}"); // 失效緩存
    return $ok;
}

注意: 緩存非強一致性,接受「短暫髒讀」。強一致性場景直接查 DB 或用分散式鎖。

安全加固:四層防護

層級措施實施
網路內網隔離Memcached 僅綁定內網 IP (-l 10.0.1.10),安全組/防火牆僅放行應用伺服器 IP
防火牆iptables/nftablesiptables -A INPUT -p tcp -s 10.0.1.0/24 --dport 11211 -j ACCEPT
iptables -A INPUT -p tcp --dport 11211 -j DROP
認證SASL (需 memcached 1.4.3+ + php-memcached)啟用 -S 參數,客戶端設定用戶/密碼。php-memcache 不支援 SASL,升級 php-memcached
監控異常存取告警Prometheus memcached_exporter + Grafana 儀表板,監控 cmd_get/cmd_set 突增、連線數異常

遷移建議:Memcache → Memcached / Redis

  1. php-memcached:支援 SASL、Binary Protocol、更豐富 API(touch、cas、getDelayed),直接替換類名即可遷移 90% 代碼。
  2. Redis:資料結構豐富(List/Set/Sorted Set/Stream)、原生支援發布訂閱、Lua 腳本、持久化、集群模式。適用於排行榜、分散式鎖、即時通訊等 Memcache 無法勝任的場景。
  3. 遷移策略:雙寫過渡期 → 讀取切換 → 停寫舊端。

總結

Memcache 以極簡的 K-V 記憶體存儲、原子增減、多節點一致性雜湊,成為「緩存層」的經典選擇。掌握 addServer 池管理、set/get/increment 核心操作、鍵設計與安全隔離,即可構建高效能緩存體系。新專案優先選擇 php-memcached + Redis 混合架構,發揮各自優勢。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved