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

PHP 使用 Memcache 實現進程鎖的完整類封裝與應用實戰

     編輯:PHP 綜合知識

前言

在高併發的 PHP 應用中,進程鎖是防止競爭條件、保證數據一致性的關鍵機制。本文分享一個基於 Memcache 封裝的進程鎖類,支援自動重試、超時回調、連接復用等企業級特性,適合分佈式環境下的鎖控制場景。

核心類設計:lock_processlock

該類封裝了鎖的獲取、釋放、重試邏輯及異常處理,主要屬性包括:

  • $sLockKeyPre:鍵名前綴,避免業務鍵衝突
  • $iLockRetryInterval:重試間隔(微秒)
  • $iLockRetryCount:最大重試次數
  • $iLockCacheTimeout:鎖自動過期時間,防止死鎖
  • $onLockTimeoutFunc:獲取鎖失敗時的回調處理
  • $oMemcache:Memcache 連接實例(單例模式)

關鍵方法解析

1. 連接管理

public function connect() {
    if (!isset($this->oMemcache)) {
        $this->oMemcache = new Memcache();
        $this->oMemcache->connect('127.0.0.1', 11211);
    }
    return $this->oMemcache;
}

採用惰性初始化,確保全局僅建立一個連接,減少資源開銷。

2. 原子性加鎖操作

public function addMemcache($sKey, $sValue, $iTimeout) {
    for ($i = 0; $i < $this->iMemcacheRetryCount; $i++) {
        $bRes = $this->oMemcache->add($sKey, $sValue, $iTimeout);
        if ($bRes) return true;
        usleep($this->iLockRetryInterval * 1000);
    }
    return false;
}

利用 Memcache add 命令的原子性(僅當 key 不存在時寫入成功)實現「檢查並設置」(CAS)語義,配合重試機制應對高併發搶鎖。

3. 完整鎖流程控制

public function lock($sLockID) {
    $oMemcache = $this->connect();
    $sKey = $this->sLockKeyPre . $sLockID;

    for ($i = 0; $i < $this->iLockRetryCount; $i++) {
        if ($this->addMemcache($sKey, '1', $this->iLockCacheTimeout)) {
            return true;
        }
        usleep($this->iLockRetryInterval * 1000);
    }

    // 重試耗盡,觸發超時回調
    if (is_callable($this->onLockTimeoutFunc)) {
        call_user_func($this->onLockTimeoutFunc);
    }
    return false;
}

4. 安全釋放鎖

public function unlock($sLockID) {
    $oMemcache = $this->connect();
    $sKey = $this->sLockKeyPre . $sLockID;
    return $this->oMemcache->delete($sKey);
}

直接刪除 key 釋放鎖,簡單高效。生產環境建議加入「僅刪除自己持有的鎖」邏輯(如存入進程 ID 校驗),防止誤刪他人鎖。

應用示例

$oLock = new lock_processlock();
$lockResource = "order_process_123";

// 獲取鎖
if ($oLock->lock($lockResource)) {
    try {
        // 執行核心業務:扣庫存、寫訂單、發 MQ 等
        processOrder($lockResource);
    } finally {
        // 確保釋放鎖
        $oLock->unlock($lockResource);
    }
} else {
    // 可選:記錄日誌、拋異常、排隊重試
    logError("獲取鎖失敗: $lockResource");
}

生產環境優化建議

  1. 鎖值存入持有者標識:$sValue = getmypid() . '_' . microtime(true),解鎖前校驗防止誤刪。
  2. 引入 Lua 腳本:將「校驗值並刪除」封裝為原子操作,避免網絡抖動導致釋放異常。
  3. 監控與告警:記錄鎖等待時間、重試次數、超時頻率,及時發現熱點資源爭用。
  4. 考慮 Redlock 算法:多實例 Memcache/Redis 部署時,使用 Redlock 保證高可用性。

總結

本文提供的 lock_processlock 類結構清晰、功能完備,可直接應用於訂單處理、庫存扣減、定時任務防重等場景。理解其基於 Memcache add 原子特性的實現原理,有助於在更複雜的分佈式架構中設計更健壯的鎖機制。

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