OpenAI
<?php
/*** Snowflake 雪花算法生成器* 生成的 64 位 ID 結構:* 1 位 保留位(始終為0,防止負數)* 41 位 時間戳(毫秒級,當前時間減去自定義紀元)* 5 位 數據中心ID* 5 位 機器ID* 12 位 序列號(同一毫秒內生成多個 ID)*/
class Snowflake
{// 自定義紀元(起始時間戳),可根據實際情況調整private $twepoch = 1288834974657;// 各部分占用的位數private $workerIdBits = 5; // 機器ID位數private $datacenterIdBits = 5; // 數據中心ID位數private $sequenceBits = 12; // 序列號位數// 各部分的最大數值(通過位運算計算)private $maxWorkerId;private $maxDatacenterId;private $sequenceMask;// 各部分左移位數private $workerIdShift;private $datacenterIdShift;private $timestampLeftShift;// 工作機器ID和數據中心ID(取值范圍 0 ~ 最大值)private $workerId;private $datacenterId;// 序列號,記錄同一毫秒內生成的ID序號private $sequence = 0;// 上一次生成ID的時間戳,初始化為 -1private $lastTimestamp = -1;/*** 構造函數** @param int $workerId 機器ID(0 ~ 31)* @param int $datacenterId 數據中心ID(0 ~ 31)*/public function __construct($workerId, $datacenterId){// 計算各部分最大值:如 -1 << 5 得到 0b11111 (31)$this->maxWorkerId = -1 ^ (-1 << $this->workerIdBits);$this->maxDatacenterId = -1 ^ (-1 << $this->datacenterIdBits);// 序列號最大值(4095:12位全1)$this->sequenceMask = -1 ^ (-1 << $this->sequenceBits);// 檢查傳入的機器ID和數據中心ID是否合法if ($workerId > $this->maxWorkerId || $workerId < 0) {throw new Exception("機器ID必須在 0 到 " . $this->maxWorkerId . " 之間");}if ($datacenterId > $this->maxDatacenterId || $datacenterId < 0) {throw new Exception("數據中心ID必須在 0 到 " . $this->maxDatacenterId . " 之間");}$this->workerId = $workerId;$this->datacenterId = $datacenterId;// 計算各部分需要左移的位數// 序列號占用 12 位,因此機器ID需要左移 12 位$this->workerIdShift = $this->sequenceBits;// 數據中心ID需要左移 12 + 5 = 17 位$this->datacenterIdShift = $this->sequenceBits + $this->workerIdBits;// 時間戳需要左移 12 + 5 + 5 = 22 位$this->timestampLeftShift = $this->sequenceBits + $this->workerIdBits + $this->datacenterIdBits;}/*** 生成下一個唯一ID** @return int 64位的唯一ID*/public function nextId(){// 獲取當前毫秒級時間戳$timestamp = $this->timeGen();// 如果當前時間小于上一次生成ID的時間戳,則說明系統時鐘回撥,無法生成IDif ($timestamp < $this->lastTimestamp) {throw new Exception("時鐘回撥異常,拒絕生成ID. 差值: " . ($this->lastTimestamp - $timestamp) . " 毫秒");}// 如果當前時間與上次生成ID時間相同,表示同一毫秒內生成多個IDif ($timestamp == $this->lastTimestamp) {// 序列號自增,并通過位運算確保在 12 位內(最大值為 4095)$this->sequence = ($this->sequence + 1) & $this->sequenceMask;// 如果序列號達到最大值,則等待下一毫秒if ($this->sequence == 0) {$timestamp = $this->tilNextMillis($this->lastTimestamp);}} else {// 不同毫秒內,序列號重置為 0$this->sequence = 0;}// 更新上一次生成ID的時間戳$this->lastTimestamp = $timestamp;/*** 拼接各部分生成最終ID:* 1. (當前時間戳 - 自定義紀元) 左移 TIMESTAMP_LEFT_SHIFT 位* 2. 數據中心ID左移 DATACENTER_ID_SHIFT 位* 3. 機器ID左移 WORKER_ID_SHIFT 位* 4. 序列號(低12位)* 最終通過按位或(|)運算組合成一個 64 位的整數*/$id = (($timestamp - $this->twepoch) << $this->timestampLeftShift)| ($this->datacenterId << $this->datacenterIdShift)| ($this->workerId << $this->workerIdShift)| $this->sequence;return $id;}/*** 等待直到下一毫秒** @param int $lastTimestamp 上次生成ID的時間戳* @return int 下一毫秒的時間戳*/private function tilNextMillis($lastTimestamp){$timestamp = $this->timeGen();// 循環等待直到時間戳發生變化(進入下一毫秒)while ($timestamp <= $lastTimestamp) {$timestamp = $this->timeGen();}return $timestamp;}/*** 獲取當前時間戳(毫秒級)** @return int 當前毫秒級時間戳*/private function timeGen(){// microtime(true) 返回秒為單位的小數,將其乘以 1000 轉換為毫秒return (int) (microtime(true) * 1000);}
}// ------------------------- 測試示例 ------------------------- //// 創建一個 Snowflake 實例,指定機器ID和數據中心ID
try {$snowflake = new Snowflake(1, 1);// 生成 10 個唯一ID,并輸出for ($i = 0; $i < 10; $i++) {echo "生成的ID " . ($i + 1) . " : " . $snowflake->nextId() . "\n";}
} catch (Exception $e) {echo "異常:" . $e->getMessage();
}
?>
DeepSeek
<?php/*** 雪花算法分布式ID生成器* 結構:0 | 時間戳(41位) | 數據中心ID(5位) | 機器ID(5位) | 序列號(12位)*/
class Snowflake
{// 起始時間戳(2024-01-01 00:00:00 UTC)const EPOCH = 1704067200000;// 位數分配const SEQUENCE_BITS = 12; // 序列號位數const MACHINE_BITS = 5; // 機器標識位數const DATACENTER_BITS = 5; // 數據中心位數// 最大值計算(位運算優化)const MAX_SEQUENCE = -1 ^ (-1 << self::SEQUENCE_BITS);const MAX_MACHINE = -1 ^ (-1 << self::MACHINE_BITS);const MAX_DATACENTER = -1 ^ (-1 << self::DATACENTER_BITS);// 移位偏移量計算const TIMESTAMP_SHIFT = self::SEQUENCE_BITS + self::MACHINE_BITS + self::DATACENTER_BITS;const DATACENTER_SHIFT = self::SEQUENCE_BITS + self::MACHINE_BITS;const MACHINE_SHIFT = self::SEQUENCE_BITS;private $machineId; // 機器標識IDprivate $datacenterId; // 數據中心IDprivate $sequence = 0; // 序列號private $lastTimestamp = -1; // 上次生成時間戳/*** 構造函數* @param int $machineId 機器ID (0~31)* @param int $datacenterId 數據中心ID (0~31)*/public function __construct($machineId, $datacenterId){// 參數校驗if ($machineId > self::MAX_MACHINE || $machineId < 0) {throw new InvalidArgumentException("機器ID值超出范圍(0~".self::MAX_MACHINE.")");}if ($datacenterId > self::MAX_DATACENTER || $datacenterId < 0) {throw new InvalidArgumentException("數據中心ID值超出范圍(0~".self::MAX_DATACENTER.")");}$this->machineId = $machineId;$this->datacenterId = $datacenterId;}/*** 生成下一個分布式ID* @return int 64位整型ID(PHP中實際返回字符串類型以保證精度)*/public function generateId(){$timestamp = $this->getCurrentTimestamp();// 時鐘回撥檢查if ($timestamp < $this->lastTimestamp) {$diff = $this->lastTimestamp - $timestamp;throw new RuntimeException("系統時鐘回撥 {$diff} 毫秒");}// 同一毫秒內生成if ($this->lastTimestamp == $timestamp) {$this->sequence = ($this->sequence + 1) & self::MAX_SEQUENCE;// 序列號耗盡,等待下一毫秒if ($this->sequence == 0) {$timestamp = $this->waitNextMillis($this->lastTimestamp);}} else {// 新時間戳重置序列號$this->sequence = 0;}$this->lastTimestamp = $timestamp;// 組合各部分數據$id = (($timestamp) << self::TIMESTAMP_SHIFT)| ($this->datacenterId << self::DATACENTER_SHIFT)| ($this->machineId << self::MACHINE_SHIFT)| $this->sequence;// 返回字符串類型以避免32位系統精度丟失return (string)$id;}/*** 阻塞到下一毫秒* @param int $lastTimestamp 上次生成時間戳* @return int 當前時間戳*/private function waitNextMillis($lastTimestamp){$timestamp = $this->getCurrentTimestamp();while ($timestamp <= $lastTimestamp) {usleep(1000); // 休眠1毫秒$timestamp = $this->getCurrentTimestamp();}return $timestamp;}/*** 獲取當前時間戳(毫秒)* @return int 毫秒時間戳*/private function getCurrentTimestamp(){return round(microtime(true) * 1000) - self::EPOCH;}
}/* 使用示例 */
try {$snowflake = new Snowflake(1, 1); // 機器ID=1,數據中心ID=1// 生成10個IDfor ($i = 0; $i < 10; $i++) {echo $snowflake->generateId() . PHP_EOL;}
} catch (Exception $e) {echo $e->getMessage();
}
Kimi
<?php/*** 雪花算法生成唯一ID* 基于Twitter的Snowflake算法,生成一個64位的唯一ID*/
class Snowflake
{// 以下是各個部分所占的位數const SIGN_BIT = 1; // 符號位,始終為0const TIMESTAMP_BIT = 41; // 時間戳位數const DATA_CENTER_ID_BIT = 5; // 數據中心ID位數const WORKER_ID_BIT = 5; // 機器節點ID位數const SEQUENCE_BIT = 12; // 序列號位數// 最大值const MAX_DATA_CENTER_ID = -1 ^ (-1 << self::DATA_CENTER_ID_BIT); // 31const MAX_WORKER_ID = -1 ^ (-1 << self::WORKER_ID_BIT); // 31const MAX_SEQUENCE = -1 ^ (-1 << self::SEQUENCE_BIT); // 4095// 每一部分的偏移量const DATA_CENTER_ID_SHIFT = self::SEQUENCE_BIT;const WORKER_ID_SHIFT = self::SEQUENCE_BIT + self::DATA_CENTER_ID_BIT;const TIMESTAMP_SHIFT = self::SEQUENCE_BIT + self::DATA_CENTER_ID_BIT + self::WORKER_ID_BIT;// 開始時間戳(2023-01-01 00:00:00的毫秒數)const EPOCH = 1672502400000;// 數據中心ID和機器節點IDprivate $dataCenterId;private $workerId;// 序列號private $sequence = 0;// 上一次的時間戳private $lastTimestamp = -1;/*** 構造函數* @param int $dataCenterId 數據中心ID* @param int $workerId 機器節點ID*/public function __construct($dataCenterId = 0, $workerId = 0){if ($dataCenterId > self::MAX_DATA_CENTER_ID || $dataCenterId < 0) {throw new \InvalidArgumentException("dataCenterId不能大于" . self::MAX_DATA_CENTER_ID . "或小于0");}if ($workerId > self::MAX_WORKER_ID || $workerId < 0) {throw new \InvalidArgumentException("workerId不能大于" . self::MAX_WORKER_ID . "或小于0");}$this->dataCenterId = $dataCenterId;$this->workerId = $workerId;}/*** 生成唯一ID* @return int 唯一ID*/public function generateId(){$currentTimestamp = $this->getCurrentTimestamp();if ($currentTimestamp < $this->lastTimestamp) {throw new \RuntimeException("時間戳回退,拒絕生成ID");}if ($currentTimestamp == $this->lastTimestamp) {$this->sequence = ($this->sequence + 1) & self::MAX_SEQUENCE;if ($this->sequence == 0) {$currentTimestamp = $this->tilNextMillis($this->lastTimestamp);}} else {$this->sequence = 0;}$this->lastTimestamp = $currentTimestamp;// ID拼接$id = (($currentTimestamp - self::EPOCH) << self::TIMESTAMP_SHIFT)| ($this->dataCenterId << self::DATA_CENTER_ID_SHIFT)| ($this->workerId << self::WORKER_ID_SHIFT)| $this->sequence;return $id;}/*** 等待下一毫秒* @param int $lastTimestamp 上一次的時間戳* @return int 當前時間戳*/private function tilNextMillis($lastTimestamp){$timestamp = $this->getCurrentTimestamp();while ($timestamp <= $lastTimestamp) {$timestamp = $this->getCurrentTimestamp();}return $timestamp;}/*** 獲取當前時間戳(毫秒)* @return int 當前時間戳*/private function getCurrentTimestamp(){return round(microtime(true) * 1000);}
}// 使用示例
$snowflake = new Snowflake(1, 2); // 數據中心ID為1,機器節點ID為2
$id = $snowflake->generateId();
echo $id;
智譜清言
<?php/*** Snowflake ID生成類,基于Twitter的Snowflake算法*/
class Snowflake {// 雪花算法常量定義const EPOCH = 1288834974657; // 起始時間戳,單位毫秒const DATA_CENTER_ID_BITS = 5; // 數據中心ID所占的位數const MACHINE_ID_BITS = 5; // 機器ID所占的位數const SEQUENCE_BITS = 12; // 序列號所占的位數const MAX_DATA_CENTER_ID = (1 << self::DATA_CENTER_ID_BITS) - 1; // 最大的數據中心IDconst MAX_MACHINE_ID = (1 << self::MACHINE_ID_BITS) - 1; // 最大的機器IDconst MAX_SEQUENCE = (1 << self::SEQUENCE_BITS) - 1; // 最大的序列號const MACHINE_ID_SHIFT = self::SEQUENCE_BITS; // 機器ID的偏移量const DATA_CENTER_ID_SHIFT = self::MACHINE_ID_SHIFT + self::MACHINE_ID_BITS; // 數據中心ID的偏移量const TIMESTAMP_SHIFT = self::DATA_CENTER_ID_SHIFT + self::DATA_CENTER_ID_BITS; // 時間戳的偏移量private $dataCenterId; // 數據中心IDprivate $machineId; // 機器IDprivate $sequence = 0; // 序列號private $lastTimestamp = -1; // 上一次生成ID的時間戳/*** 構造函數* @param int $dataCenterId 數據中心ID,范圍0到31* @param int $machineId 機器ID,范圍0到31*/public function __construct($dataCenterId,$machineId) {if ($dataCenterId < 0 ||$dataCenterId > self::MAX_DATA_CENTER_ID) {throw new InvalidArgumentException("數據中心ID必須在0和" . self::MAX_DATA_CENTER_ID . "之間");}if ($machineId < 0 ||$machineId > self::MAX_MACHINE_ID) {throw new InvalidArgumentException("機器ID必須在0和" . self::MAX_MACHINE_ID . "之間");}$this->dataCenterId =$dataCenterId;$this->machineId =$machineId;}/*** 生成下一個ID* @return string 生成的ID字符串*/public function nextId() {$timestamp =$this->timeGen();// 如果當前時間戳小于上一次的時間戳,說明時鐘回撥if ($timestamp <$this->lastTimestamp) {throw new RuntimeException("時鐘回撥,拒絕生成ID");}// 如果當前時間戳與上一次的時間戳相同,同一毫秒內生成多個IDif ($timestamp ==$this->lastTimestamp) {$this->sequence = ($this->sequence + 1) & self::MAX_SEQUENCE;// 如果序列號達到最大值,等待下一毫秒if ($this->sequence == 0) {$timestamp =$this->tilNextMillis($this->lastTimestamp);}} else {// 如果進入新的毫秒,序列號重置為0$this->sequence = 0;}// 更新上一次的時間戳$this->lastTimestamp =$timestamp;// 生成ID$id = (($timestamp - self::EPOCH) << self::TIMESTAMP_SHIFT) |($this->dataCenterId << self::DATA_CENTER_ID_SHIFT) |($this->machineId << self::MACHINE_ID_SHIFT) |$this->sequence;return strval($id);}/*** 獲取當前時間戳,單位毫秒* @return int*/private function timeGen() {return floor(microtime(true) * 1000);}/*** 等待下一毫秒,直到時間戳增加* @param int $lastTimestamp 上一次的時間戳* @return int 當前時間戳*/private function tilNextMillis($lastTimestamp) {$timestamp =$this->timeGen();while ($timestamp <=$lastTimestamp) {$timestamp =$this->timeGen();}return $timestamp;}
}// 使用示例
try {// 創建Snowflake實例,數據中心ID為1,機器ID為1$snowflake = new Snowflake(1, 1);// 生成并輸出10個唯一IDfor ($i = 0;$i < 10; $i++) {$id =$snowflake->nextId();echo $id . "\n";}// 創建另一個Snowflake實例,數據中心ID為1,機器ID為2$snowflake2 = new Snowflake(1, 2);// 生成并輸出10個唯一IDfor ($i = 0;$i < 10; $i++) {$id =$snowflake2->nextId();echo $id . "\n";}// 創建另一個Snowflake實例,數據中心ID為2,機器ID為1$snowflake3 = new Snowflake(2, 1);// 生成并輸出10個唯一IDfor ($i = 0;$i < 10; $i++) {$id =$snowflake3->nextId();echo $id . "\n";}
} catch (Exception $e) {echo "錯誤: " . $e->getMessage() . "\n";
}
Claude
<?php/*** 雪花算法(Snowflake)PHP實現* * 雪花算法是由Twitter開發的分布式ID生成算法,能夠在分布式系統中產生唯一的ID* 該算法生成的ID結構為64位長整型,由以下部分組成:* 1. 1位符號位,固定為0(表示正數)* 2. 41位時間戳(毫秒級),可使用約69年* 3. 10位工作機器ID,包括5位數據中心ID和5位機器ID,最多支持32個數據中心和每個中心下32臺機器* 4. 12位序列號,1毫秒內最多生成4096個ID*/
class Snowflake {/*** 開始時間戳(2020-01-01)* 這是算法的基準時間,用于計算相對時間戳*/const START_TIMESTAMP = 1577808000000; // 2020-01-01 00:00:00 GMT/*** 各部分占用的位數*/const SEQUENCE_BITS = 12; // 序列號占用的位數const MACHINE_ID_BITS = 5; // 機器ID占用的位數const DATACENTER_ID_BITS = 5; // 數據中心ID占用的位數/*** 各部分的最大值*/const MAX_SEQUENCE = -1 ^ (-1 << self::SEQUENCE_BITS); // 序列號最大值 4095const MAX_MACHINE_ID = -1 ^ (-1 << self::MACHINE_ID_BITS); // 機器ID最大值 31const MAX_DATACENTER_ID = -1 ^ (-1 << self::DATACENTER_ID_BITS);// 數據中心ID最大值 31/*** 各部分向左的位移*/const MACHINE_ID_SHIFT = self::SEQUENCE_BITS; // 機器ID向左移12位const DATACENTER_ID_SHIFT = self::SEQUENCE_BITS + self::MACHINE_ID_BITS; // 數據中心ID向左移17位const TIMESTAMP_SHIFT = self::SEQUENCE_BITS + self::MACHINE_ID_BITS + self::DATACENTER_ID_BITS; // 時間戳向左移22位/*** 數據中心ID* @var int*/private $datacenterId;/*** 機器ID* @var int*/private $machineId;/*** 毫秒內序列號* @var int*/private $sequence = 0;/*** 上次生成ID的時間戳* @var int*/private $lastTimestamp = -1;/*** 構造函數* * @param int $datacenterId 數據中心ID (0~31)* @param int $machineId 機器ID (0~31)* @throws Exception 當數據中心ID或機器ID超出范圍時拋出異常*/public function __construct($datacenterId, $machineId) {// 參數校驗if ($datacenterId > self::MAX_DATACENTER_ID || $datacenterId < 0) {throw new Exception("數據中心ID不能大于".self::MAX_DATACENTER_ID."或小于0");}if ($machineId > self::MAX_MACHINE_ID || $machineId < 0) {throw new Exception("機器ID不能大于".self::MAX_MACHINE_ID."或小于0");}$this->datacenterId = $datacenterId;$this->machineId = $machineId;}/*** 獲取當前時間戳(毫秒)* * @return int 當前時間戳(毫秒)*/private function getCurrentTimestamp() {// 獲取當前時間戳,單位為毫秒return floor(microtime(true) * 1000);}/*** 阻塞到下一個毫秒,直到獲得新的時間戳* * @param int $lastTimestamp 上次生成ID的時間戳* @return int 新的時間戳*/private function waitNextMillis($lastTimestamp) {$timestamp = $this->getCurrentTimestamp();while ($timestamp <= $lastTimestamp) {$timestamp = $this->getCurrentTimestamp();}return $timestamp;}/*** 生成ID* * @return string 返回生成的ID(字符串形式,因為PHP整數范圍有限)* @throws Exception 當時鐘回撥時拋出異常*/public function nextId() {// 獲取當前時間戳$timestamp = $this->getCurrentTimestamp();// 如果當前時間小于上一次ID生成的時間戳,說明系統時鐘回退過,拋出異常if ($timestamp < $this->lastTimestamp) {throw new Exception("時鐘向后移動,拒絕生成ID,時間差: " . ($this->lastTimestamp - $timestamp) . " 毫秒");}// 如果是同一時間生成的,則進行毫秒內序列號遞增if ($timestamp == $this->lastTimestamp) {// 序列號遞增$this->sequence = ($this->sequence + 1) & self::MAX_SEQUENCE;// 同一毫秒內序列號已經達到最大值,阻塞到下一個毫秒if ($this->sequence == 0) {$timestamp = $this->waitNextMillis($this->lastTimestamp);}} else {// 時間戳改變,毫秒內序列號重置為0$this->sequence = 0;}// 記錄上次生成ID的時間戳$this->lastTimestamp = $timestamp;// 計算相對時間戳(與起始時間的差值)$relativeTimestamp = $timestamp - self::START_TIMESTAMP;// 組裝ID并返回// 使用字符串拼接,避免PHP整數溢出問題$id = (($relativeTimestamp << self::TIMESTAMP_SHIFT) |($this->datacenterId << self::DATACENTER_ID_SHIFT) |($this->machineId << self::MACHINE_ID_SHIFT) |$this->sequence);// 轉換為字符串,避免潛在的整數溢出問題return (string)$id;}
}// 使用示例
try {// 創建一個雪花算法實例,參數為數據中心ID和機器ID$snowflake = new Snowflake(1, 1);// 生成ID$id = $snowflake->nextId();echo "生成的ID: " . $id . PHP_EOL;// 批量生成多個IDecho "批量生成5個ID:" . PHP_EOL;for ($i = 0; $i < 5; $i++) {echo $snowflake->nextId() . PHP_EOL;}
} catch (Exception $e) {echo "錯誤: " . $e->getMessage() . PHP_EOL;
}
?>
豆包
<?phpclass Snowflake {// 起始時間戳,一般設置為項目開始的時間,單位:毫秒const EPOCH = 1609459200000; // 數據中心 ID 所占的位數const DATA_CENTER_ID_BITS = 5; // 機器 ID 所占的位數const WORKER_ID_BITS = 5; // 序列號所占的位數const SEQUENCE_BITS = 12; // 數據中心 ID 最大值const MAX_DATA_CENTER_ID = -1 ^ (-1 << self::DATA_CENTER_ID_BITS); // 機器 ID 最大值const MAX_WORKER_ID = -1 ^ (-1 << self::WORKER_ID_BITS); // 序列號最大值const MAX_SEQUENCE = -1 ^ (-1 << self::SEQUENCE_BITS); // 機器 ID 向左移位數const WORKER_ID_SHIFT = self::SEQUENCE_BITS; // 數據中心 ID 向左移位數const DATA_CENTER_ID_SHIFT = self::SEQUENCE_BITS + self::WORKER_ID_BITS; // 時間戳向左移位數const TIMESTAMP_LEFT_SHIFT = self::SEQUENCE_BITS + self::WORKER_ID_BITS + self::DATA_CENTER_ID_BITS; // 數據中心 IDprivate $dataCenterId; // 機器 IDprivate $workerId; // 序列號private $sequence = 0; // 上一次生成 ID 的時間戳private $lastTimestamp = -1; /*** 構造函數,初始化數據中心 ID 和機器 ID** @param int $dataCenterId 數據中心 ID* @param int $workerId 機器 ID* @throws Exception 如果數據中心 ID 或機器 ID 超出范圍,拋出異常*/public function __construct($dataCenterId, $workerId) {// 檢查數據中心 ID 是否在合法范圍內if ($dataCenterId > self::MAX_DATA_CENTER_ID || $dataCenterId < 0) {throw new Exception("Data center ID must be between 0 and " . self::MAX_DATA_CENTER_ID);}// 檢查機器 ID 是否在合法范圍內if ($workerId > self::MAX_WORKER_ID || $workerId < 0) {throw new Exception("Worker ID must be between 0 and " . self::MAX_WORKER_ID);}$this->dataCenterId = $dataCenterId;$this->workerId = $workerId;}/*** 生成下一個唯一的 ID** @return int 生成的唯一 ID* @throws Exception 如果系統時鐘回撥,拋出異常*/public function nextId() {// 獲取當前時間戳,單位:毫秒$timestamp = $this->getCurrentTimestamp();// 處理時鐘回撥問題if ($timestamp < $this->lastTimestamp) {throw new Exception("Clock moved backwards. Refusing to generate id for " . ($this->lastTimestamp - $timestamp) . " milliseconds");}if ($timestamp == $this->lastTimestamp) {// 如果在同一毫秒內,序列號遞增$this->sequence = ($this->sequence + 1) & self::MAX_SEQUENCE;if ($this->sequence == 0) {// 序列號達到最大值,等待下一毫秒$timestamp = $this->waitNextMillis($this->lastTimestamp);}} else {// 時間戳改變,重置序列號$this->sequence = 0;}// 更新上一次生成 ID 的時間戳$this->lastTimestamp = $timestamp;// 生成最終的 IDreturn (($timestamp - self::EPOCH) << self::TIMESTAMP_LEFT_SHIFT) |($this->dataCenterId << self::DATA_CENTER_ID_SHIFT) |($this->workerId << self::WORKER_ID_SHIFT) |$this->sequence;}/*** 獲取當前時間戳,單位:毫秒** @return int 當前時間戳*/private function getCurrentTimestamp() {return floor(microtime(true) * 1000);}/*** 等待下一毫秒** @param int $lastTimestamp 上一次生成 ID 的時間戳* @return int 下一毫秒的時間戳*/private function waitNextMillis($lastTimestamp) {$timestamp = $this->getCurrentTimestamp();while ($timestamp <= $lastTimestamp) {$timestamp = $this->getCurrentTimestamp();}return $timestamp;}
}// 使用示例
try {// 創建 Snowflake 實例,指定數據中心 ID 和機器 ID$snowflake = new Snowflake(1, 1);// 生成唯一 ID$id = $snowflake->nextId();echo "Generated ID: " . $id;
} catch (Exception $e) {echo "Error: " . $e->getMessage();
}
騰訊元寶
<?php
class Snowflake
{// 數據中心ID所占位數(5位,支持32個數據中心)const DATA_CENTER_ID_BITS = 5;// 機器ID所占位數(5位,支持32臺機器)const MACHINE_ID_BITS = 5;// 序列號所占位數(12位,每毫秒支持4096個ID)const SEQUENCE_BITS = 12;// 最大數據中心ID(2^5 - 1)const MAX_DATA_CENTER_ID = -1 ^ (-1 << self::DATA_CENTER_ID_BITS);// 最大機器ID(2^5 - 1)const MAX_MACHINE_ID = -1 ^ (-1 << self::MACHINE_ID_BITS);// 時間戳左移位數(41+5+5=51位)const TIMESTAMP_LEFT_SHIFT = self::SEQUENCE_BITS + self::MACHINE_ID_BITS + self::DATA_CENTER_ID_BITS;// 機器ID左移位數(41+5=46位)const SEQUENCE_LEFT_SHIFT = self::MACHINE_ID_BITS + self::DATA_CENTER_ID_BITS;// 起始時間戳(2021-01-01 00:00:00,可自定義)private $epoch = 1609430400000;// 實例屬性private int $datacenterId; // 數據中心IDprivate int $machineId; // 機器IDprivate int $sequence = 0; // 序列號private int $lastTimestamp = -1; // 上次生成ID的時間戳/*** 構造函數,初始化ID生成器* @param int $datacenterId 數據中心ID(0-31)* @param int $machineId 機器ID(0-31)* @throws Exception 如果ID超出范圍*/public function __construct(int $datacenterId, int $machineId){// 驗證數據中心ID范圍if ($datacenterId < 0 || $datacenterId > self::MAX_DATA_CENTER_ID) {throw new Exception("數據中心ID超出范圍");}// 驗證機器ID范圍if ($machineId < 0 || $machineId > self::MAX_MACHINE_ID) {throw new Exception("機器ID超出范圍");}$this->datacenterId = $datacenterId;$this->machineId = $machineId;}/*** 生成唯一ID* @return int 64位唯一ID* @throws Exception 如果時鐘發生回撥*/public function nextId(): int{$timestamp = $this->currentTimeMillis();// 檢測時鐘回撥if ($timestamp < $this->lastTimestamp) {throw new Exception("錯誤:系統時鐘發生回撥");}// 同一毫秒內處理序列號遞增if ($this->lastTimestamp === $timestamp) {$this->sequence = ($this->sequence + 1) & ((1 << self::SEQUENCE_BITS) - 1);// 序列號溢出,等待下一毫秒if ($this->sequence === 0) {$timestamp = $this->waitNextMillis($timestamp);}} else {// 新的一毫秒,重置序列號$this->sequence = 0;}// 更新上次時間戳$this->lastTimestamp = $timestamp;// 組合ID:(時間戳 << 22) | (數據中心ID << 17) | (機器ID << 12) | 序列號return (($timestamp - $this->epoch) << self::TIMESTAMP_LEFT_SHIFT) |($this->datacenterId << self::SEQUENCE_LEFT_SHIFT) |($this->machineId << self::SEQUENCE_BITS) |$this->sequence;}/*** 等待下一毫秒* @param int $lastTimestamp 上次時間戳* @return int 下一毫秒時間戳*/private function waitNextMillis(int $lastTimestamp): int{$timestamp = $this->currentTimeMillis();while ($timestamp <= $lastTimestamp) {$timestamp = $this->currentTimeMillis();}return $timestamp;}/*** 獲取當前時間戳(毫秒級)* @return int*/private function currentTimeMillis(): int{return (int)(microtime(true) * 1000);}
}// 使用示例
$datacenterId = 1; // 數據中心ID(0-31)
$machineId = 1; // 機器ID(0-31)
$snowflake = new Snowflake($datacenterId, $machineId);for ($i = 0; $i < 10; $i++) {$userId = $snowflake->nextId();echo "生成的用戶ID: {$userId}<br/>";
}
Vercel
<?php/*** 雪花算法(Snowflake)PHP實現* * 雪花算法是由Twitter開發的分布式唯一ID生成算法,結構如下:* 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000* * 第1位:符號位,始終為0* 第2-42位:41位時間戳(毫秒級),可以使用69年* 第43-43位:1位數據中心ID* 第44-48位:5位機器ID* 第49-53位:5位數據中心內機器ID* 第54-64位:12位序列號,毫秒內的計數,12位的計數順序號支持每個節點每毫秒產生4096個ID序號*/
class Snowflake {/*** 開始時間戳(2020-01-01)* 這是一個自定義的起始時間,用于計算相對時間戳*/const START_TIMESTAMP = 1577808000000; // 2020-01-01 00:00:00 GMT/*** 各部分占用的位數*/const SEQUENCE_BITS = 12; // 序列號占用的位數const MACHINE_ID_BITS = 5; // 機器ID占用的位數const DATACENTER_ID_BITS = 5; // 數據中心ID占用的位數/*** 各部分的最大值*/const MAX_SEQUENCE = -1 ^ (-1 << self::SEQUENCE_BITS); // 序列號最大值 4095const MAX_MACHINE_ID = -1 ^ (-1 << self::MACHINE_ID_BITS); // 機器ID最大值 31const MAX_DATACENTER_ID = -1 ^ (-1 << self::DATACENTER_ID_BITS); // 數據中心ID最大值 31/*** 各部分向左的位移*/const MACHINE_ID_SHIFT = self::SEQUENCE_BITS; // 機器ID向左移12位const DATACENTER_ID_SHIFT = self::SEQUENCE_BITS + self::MACHINE_ID_BITS; // 數據中心ID向左移17位const TIMESTAMP_SHIFT = self::SEQUENCE_BITS + self::MACHINE_ID_BITS + self::DATACENTER_ID_BITS; // 時間戳向左移22位/*** @var int 數據中心ID*/private $datacenterId;/*** @var int 機器ID*/private $machineId;/*** @var int 毫秒內序列號*/private $sequence = 0;/*** @var int 上次生成ID的時間戳*/private $lastTimestamp = -1;/*** 構造函數** @param int $datacenterId 數據中心ID (0~31)* @param int $machineId 機器ID (0~31)* @throws Exception 當數據中心ID或機器ID超出范圍時拋出異常*/public function __construct($datacenterId = 0, $machineId = 0) {// 檢查數據中心ID和機器ID是否在有效范圍內if ($datacenterId > self::MAX_DATACENTER_ID || $datacenterId < 0) {throw new Exception("數據中心ID超出范圍: 應為0~" . self::MAX_DATACENTER_ID);}if ($machineId > self::MAX_MACHINE_ID || $machineId < 0) {throw new Exception("機器ID超出范圍: 應為0~" . self::MAX_MACHINE_ID);}$this->datacenterId = $datacenterId;$this->machineId = $machineId;}/*** 獲取下一個ID** @return string 生成的ID(返回字符串是因為PHP的整數范圍可能不足以存儲64位ID)* @throws Exception 當時鐘回撥時拋出異常*/public function nextId() {// 獲取當前時間戳(毫秒)$timestamp = $this->getCurrentTimestamp();// 檢查時鐘回撥if ($timestamp < $this->lastTimestamp) {throw new Exception("時鐘回撥,拒絕生成ID,上次時間: " . $this->lastTimestamp . ", 當前時間: " . $timestamp);}// 如果是同一毫秒內,則增加序列號if ($timestamp == $this->lastTimestamp) {// 序列號遞增$this->sequence = ($this->sequence + 1) & self::MAX_SEQUENCE;// 如果序列號溢出,則等待下一毫秒if ($this->sequence == 0) {$timestamp = $this->waitNextMillis($this->lastTimestamp);}} else {// 不同毫秒內,序列號重置為0$this->sequence = 0;}// 更新上次生成ID的時間戳$this->lastTimestamp = $timestamp;// 計算相對時間戳(相對于開始時間)$timestampDiff = $timestamp - self::START_TIMESTAMP;// 組合各部分生成ID// 注意:PHP的整數范圍可能不足以存儲64位ID,所以使用字符串或GMP擴展處理大整數$id = (($timestampDiff << self::TIMESTAMP_SHIFT) |($this->datacenterId << self::DATACENTER_ID_SHIFT) |($this->machineId << self::MACHINE_ID_SHIFT) |$this->sequence);return (string)$id;}/*** 獲取當前時間戳(毫秒)** @return int 當前時間戳(毫秒)*/private function getCurrentTimestamp() {// 獲取微秒級時間戳并轉換為毫秒return (int)floor(microtime(true) * 1000);}/*** 等待下一毫秒** @param int $lastTimestamp 上次生成ID的時間戳* @return int 新的時間戳(毫秒)*/private function waitNextMillis($lastTimestamp) {$timestamp = $this->getCurrentTimestamp();// 循環等待,直到獲得新的時間戳while ($timestamp <= $lastTimestamp) {$timestamp = $this->getCurrentTimestamp();}return $timestamp;}
}// 使用示例
try {// 創建雪花算法實例,參數為數據中心ID和機器ID$snowflake = new Snowflake(1, 1);// 生成10個IDecho "生成的ID示例:\n";for ($i = 0; $i < 10; $i++) {echo $snowflake->nextId() . "\n";}
} catch (Exception $e) {echo "錯誤: " . $e->getMessage();
}
?>
文心一言
<?phpclass Snowflake {// 定義雪花ID的各部分位數private const TIMESTAMP_BITS = 41; // 時間戳位數private const NODE_ID_BITS = 10; // 節點ID位數private const SEQUENCE_BITS = 12; // 序列號位數// 定義起始時間戳(這里以2020-01-01為例)private const EPOCH = 1577836800000;// 定義最大取值范圍private const MAX_NODE_ID = (1 << self::NODE_ID_BITS) - 1;private const MAX_SEQUENCE = (1 << self::SEQUENCE_BITS) - 1;// 定義偏移量private const TIMESTAMP_SHIFT = self::NODE_ID_BITS + self::SEQUENCE_BITS;private const NODE_ID_SHIFT = self::SEQUENCE_BITS;private $nodeId; // 節點IDprivate $lastTimestamp = -1; // 上次生成ID的時間戳private $sequence = 0; // 序列號/*** 構造函數,用于初始化節點ID** @param int $nodeId 節點ID* @throws InvalidArgumentException 如果節點ID超出范圍*/public function __construct($nodeId) {if ($nodeId < 0 || $nodeId > self::MAX_NODE_ID) {throw new InvalidArgumentException("Invalid node ID, must be between 0 and " . self::MAX_NODE_ID);}$this->nodeId = $nodeId;}/*** 生成下一個唯一的ID** @return int 生成的唯一ID* @throws RuntimeException 如果系統時鐘回撥*/public function generateId() {$currentTimestamp = $this->timestamp();// 檢查時鐘回撥if ($currentTimestamp < $this->lastTimestamp) {throw new RuntimeException("Clock moved backwards");}// 如果當前時間戳與上次相同,則遞增序列號if ($currentTimestamp == $this->lastTimestamp) {$this->sequence = ($this->sequence + 1) & self::MAX_SEQUENCE;// 如果序列號溢出,則等待下一毫秒if ($this->sequence == 0) {$currentTimestamp = $this->untilNextMillis($this->lastTimestamp);}} else {// 如果時間戳不同,則重置序列號$this->sequence = 0;}// 更新上次生成ID的時間戳$this->lastTimestamp = $currentTimestamp;// 組合時間戳、節點ID和序列號生成唯一的IDreturn (($currentTimestamp - self::EPOCH) << self::TIMESTAMP_SHIFT) |($this->nodeId << self::NODE_ID_SHIFT) |$this->sequence;}/*** 獲取當前時間戳(毫秒)** @return int 當前時間戳*/private function timestamp() {return round(microtime(true) * 1000);}/*** 等待下一毫秒** @param int $lastTimestamp 上次生成ID的時間戳* @return int 下一毫秒的時間戳*/private function untilNextMillis($lastTimestamp) {$currentTimestamp = $this->timestamp();while ($currentTimestamp <= $lastTimestamp) {$currentTimestamp = $this->timestamp();}return $currentTimestamp;}
}// 示例使用
$nodeId = 1; // 設置節點ID
$snowflake = new Snowflake($nodeId);// 生成10個唯一ID
for ($i = 0; $i < 10; $i++) {$id = $snowflake->generateId();echo "Generated ID: $id\n";
}
訊飛星火
訊飛星火在生成代碼的過程中居然出現了BUG,?代碼在生成過程中,?開頭生成的代碼莫名消失,?最后生成的代碼如下
self::MAX_DATA_CENTER_ID || $dataCenterId < 0) {throw new Exception("Data Center ID can't be greater than " . self::MAX_DATA_CENTER_ID . " or less than 0");}if ($machineId > self::MAX_MACHINE_ID || $machineId < 0) {throw new Exception("Machine ID can't be greater than " . self::MAX_MACHINE_ID . " or less than 0");}$this->dataCenterId = $dataCenterId;$this->machineId = $machineId;}public function nextId() {$timestamp = $this->timeGen();if ($timestamp < $this->lastTimestamp) {throw new Exception("Clock moved backwards. Refusing to generate id for " . ($this->lastTimestamp - $timestamp) . " milliseconds");}if ($this->lastTimestamp == $timestamp) {$this->sequence = ($this->sequence + 1) & self::MAX_SEQUENCE;if ($this->sequence == 0) {$timestamp = $this->tilNextMillis($this->lastTimestamp);}} else {$this->sequence = 0;}$this->lastTimestamp = $timestamp;return (($timestamp - self::EPOCH) << self::TIMESTAMP_SHIFT) |($this->dataCenterId << self::DATA_CENTER_ID_SHIFT) |($this->machineId << self::MACHINE_ID_SHIFT) |$this->sequence;}protected function tilNextMillis($lastTimestamp) {$timestamp = $this->timeGen();while ($timestamp <= $lastTimestamp) {$timestamp = $this->timeGen();}return $timestamp;}protected function timeGen() {return round(microtime(true) * 1000); // 獲取當前時間的毫秒級時間戳}
}// 使用示例
try {$snowflake = new Snowflake(1, 1); // 數據中心ID和機器ID都設置為1echo $snowflake->nextId(); // 生成一個唯一的ID
} catch (Exception $e) {echo 'Error: ' . $e->getMessage();
}
?>