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

PHP Memcached 客戶端開發全攻略:從基礎操作到自定義 Socket 通訊協議實現

     編輯:PHP 相關知識

為什麼選擇 Memcached?

  • 極速:純內存操作,亞毫秒級延遲
  • 簡單:Key-Value 模型,無複雜查詢語法
  • 分散式:Client 端一致性哈希分片,無單點故障
  • 成熟:PHP 官方擴展 memcached (非舊 memcache) 功能完整

官方擴展核心 API 速查

分類方法說明
連接addServer(host, port, weight)加入伺服器池(不立即連接)
connect(host, port) / pconnect()立即連接單台 / 持久連接
讀寫set(key, value, expiration)存儲(覆蓋)
get(key)獲取
add(key, value, exp)鍵不存在才存儲(原子)
replace(key, value, exp)鍵存在才更新
delete(key)刪除
進階getMulti(keys)批量獲取,減少網絡往返
setMulti(items, exp)批量存儲
getStats() / getVersion()監控統計
CASget(key) 返回 token → cas(token, key, value)樂觀鎖防併發覆蓋

快速上手範例

<?php
$mc = new Memcached();
$mc->addServer('172.10.10.10', 11211); // 標準端口 11211
$mc->setOption(Memcached::OPT_BINARY_PROTOCOL, true); // 二進制協議,性能更好
$mc->setOption(Memcached::OPT_TCP_NODELAY, true);     // 關閉 Nagle 算法
$mc->setOption(Memcached::OPT_NO_BLOCK, true);        // 非阻塞 I/O
$mc->setOption(Memcached::OPT_CONNECT_TIMEOUT, 1000); // 1秒連接超時
$mc->setOption(Memcached::OPT_POLL_TIMEOUT, 2000);    // 2秒輪詢超時

// 基礎操作
$mc->set('user:1001', ['name' => 'Alice', 'vip' => true], 3600); // 1小時過期
$data = $mc->get('user:1001');
var_dump($data);

// 多鍵批量
$profiles = $mc->getMulti(['user:1001', 'user:1002', 'user:1003']);

// CAS 樂觀鎖(庫存扣減等場景)
$casToken = null;
$stock = $mc->get('product:999:stock', null, $casToken);
if ($stock > 0) {
    $mc->cas($casToken, 'product:999:stock', $stock - 1);
}

addServer vs connect 關鍵差異

$mc = new Memcached();

// 方案 A:連接池模式(推薦生產)
$mc->addServer('10.0.0.1', 11211, 30); // 權重 30
$mc->addServer('10.0.0.2', 11211, 20);
$mc->addServer('10.0.0.3', 11211, 10);
// Client 端一致性哈希自動分片,單台故障自動切換

// 方案 B:單連接模式(僅測試/單節點)
$mc->connect('10.0.0.1', 11211);
// 若先 addServer 再 connect,會忽略池子只用連接的那台

自定義客戶端:直擊 Memcached 文本協議

理解協議有助於排查疑難雜症、編寫代理、或在無擴展環境下工作。

協議基礎 (文本模式)


// 存儲
set key flags exptime bytes\r\n
value\r\n
// 回應:STORED / NOT_STORED / EXISTS / NOT_FOUND

// 獲取
get key1 key2 ...\r\n
// 回應:
VALUE key flags bytes\r\n
value\r\n
END

// 刪除
delete key\r\n
// 回應:DELETED / NOT_FOUND

純 PHP Socket 實現 Get 操作

function memcachedGet(string $host, int $port, string $key, float $timeout = 1.0): ?string {
    $fp = @fsockopen($host, $port, $errno, $errstr, $timeout);
    if (!$fp) {
        trigger_error("Memcached 連接失敗: {$errstr} ({$errno})", E_USER_WARNING);
        return null;
    }
    stream_set_timeout($fp, $timeout);

    $cmd = "get {$key}\r\n";
    fwrite($fp, $cmd);

    $response = '';
    while (!feof($fp)) {
        $line = fgets($fp, 4096);
        if ($line === false) break;
        $response .= $line;
        if (str_starts_with($line, 'END')) break;
    }
    fclose($fp);

    // 解析
    if (str_starts_with($response, 'END')) return null; // 不存在
    // VALUE key flags bytes\r\nvalue\r\nEND
    $lines = explode("\r\n", trim($response));
    if (count($lines) >= 2 && str_starts_with($lines[0], 'VALUE')) {
        return $lines[1]; // value 行
    }
    return null;
}

// 使用
$value = memcachedGet('172.10.10.10', 11211, 'mykey');
var_dump($value);

生產環境調優清單

  1. 連接池複用:PHP-FPM Worker 進程內靜態變量持有 Memcached 實例,避免每請求新建連接。
  2. 二進制協議:OPT_BINARY_PROTOCOL = true,減少解析開銷、支援 SASL 認證。
  3. 壓縮大值:setOption(Memcached::OPT_COMPRESSION, true),自動壓縮 > 100 字節值(需 zlib)。
  4. 序列化器:OPT_SERIALIZER = Memcached::SERIALIZER_IGBINARY,比 PHP 原生 serialize 快 2-3x、體積更小。
  5. 監控關鍵指標:get_hits / (get_hits + get_misses) 命中率 > 95%、evictions 激增說明內存不足、curr_connections 逼近上限需擴容。
  6. 鍵命名規範:prefix:type:id:field,如 acme:user:1001:profile,便於清理與監控。

常見坑點與避坑

現象原因解決
獲取到 false 但鍵存在值為 0、空字串、false 被誤判用 $mc->get($key, null, $cas) 檢查結果碼或 getResultCode() == Memcached::RES_SUCCESS
set 成功但 get 為空鍵名包含特殊字符/空格/超過 250 字節鍵名僅用 [a-zA-Z0-9_:.-],長度 < 200
集群下數據不一致Client 端一致性哈希環不同步所有 Client 同一配置順序 addServer,或改用 Proxy (Twemproxy/Mcrouter)
PHP 7.4+ 編譯報錯舊 memcache 擴展不支援 PHP 7+必須安裝 pecl install memcached (有 d 結尾)

總結

Memcached 以「簡單、快速、分散式」成為 PHP 高併發架構的標配緩存層。掌握官方擴展最佳實踐(連接池、二進制協議、壓縮、igbinary),並理解底層文本協議,能讓你在排查疑難雜症、設計高可用架構時遊刃有餘。記住:緩存只是加速器,永遠不要將其作為唯一數據源,業務核心數據必須落地持久化存儲。

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