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

PHP 利用系統信號量實現原子性遞增序列 ID

     編輯:PHP 綜合知識

問題背景

在多程序/執行緒環境下產生唯一遞增 ID,常見方案有:進程 ID + 時間戳(或隨機數),但 Apache 2+ 長期駐留進程易導致碰撞;或使用 MySQL 自增欄位,但效能較差且引入資料庫依賴。本文介紹使用 System V 信號量 配合共享記憶體,在無資料庫環境下實現高效、原子性的 ID 產生器。

核心概念:信號量

信號量源自鐵路單線路段管理:同一時間只允許一列火車通過。作業系統核心管理信號量狀態,提供進程間同步機制(IPC)。PHP 透過 sem_*、shm_* 函式族封裝 System V IPC,可實現跨進程的鎖定與共享資料存取。

完整實作程式碼

<?php
// 遞增序列號 ID (1~1,000,000,000)
// ID 存放於共享記憶體,透過信號量同步
$IPC_KEY = 0x1234;        // System V IPC Key
$SEQ_KEY = "SEQ";         // 共享記憶體內儲存序列號的 Key

// 取得/建立信號量
$sem_id = sem_get($IPC_KEY);

// 取得/建立共享記憶體(64 bytes)
$shm_id = shm_attach($IPC_KEY, 64);

// 佔有信號量(加鎖)
sem_acquire($sem_id);

// 從共享記憶體讀取 ID
$id = @shm_get_var($shm_id, $SEQ_KEY);
if ($id === null || $id >= 1000000000) {
    $id = 1;
} else {
    $id++;
}

// 寫回共享記憶體
shm_put_var($shm_id, $SEQ_KEY, $id);

// 釋放信號量(解鎖)
sem_release($sem_id);

// 斷開共享記憶體關聯
shm_detach($shm_id);

echo "序列號 ID: {$id}";
?>

關鍵點解析

  • 第 9-10 行:定義 IPC Key 與共享記憶體儲存 Key,PHP 僅支援 System V IPC,需透過 Key 關聯資源。
  • 第 13 行:sem_get() 取得或建立信號量。
  • 第 15 行:shm_attach() 取得或建立共享記憶體,第二參數指定大小。
  • 第 18-34 行:同步關鍵區段。sem_acquire() 佔有信號量,其他進程執行到此會阻塞,直到 sem_release() 釋放。@ 抑制首次讀取不存在 Key 時的警告。

系統層面驗證與管理

# 查看 IPC 資源
$ ipcs
------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x00001234 1212443    www-data   666        64         0

------ Semaphore Arrays --------
key        semid      owner      perms      nsems
0x00001234 163841     www-data   666        3

# 移除資源
$ ipcrm -M 0x00001234  # 移除共享記憶體
$ ipcrm -S 0x00001234  # 移除信號量

效能評估

信號量操作屬核心級原語,開銷極低,適用於高併發 ID 產生場景。若系統不支援 System V IPC(如 Windows),需考慮替代方案(如檔案鎖、Redis 原子操作等)。

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