<?php class Snowflake { // 定义Snowflake算法的各个参数 private $workerIdBits = 5; private $datacenterIdBits = 5; private $sequenceBits = 12; private $workerIdShift; private $datacenterIdShift; private $timestampLeftShift; private $maxWorkerId; private $maxDatacenterId; private $sequenceMask; private $workerId; private $datacenterId; private $sequence = 0; private $lastTimestamp = -1; public function __construct($workerId, $datacenterId) { // 计算位偏移量 $this->workerIdShift = $this->sequenceBits; $this->datacenterIdShift = $this->sequenceBits + $this->workerIdBits; $this->timestampLeftShift = $this->sequenceBits + $this->workerIdBits + $this->datacenterIdBits; // 计算最大ID $this->maxWorkerId = -1 ^ (-1 << $this->workerIdBits); $this->maxDatacenterId = -1 ^ (-1 << $this->datacenterIdBits); $this->sequenceMask = -1 ^ (-1 << $this->sequenceBits); // 初始化参数 $this->workerId = $workerId; $this->datacenterId = $datacenterId; } // 生成下一个唯一ID public function generateId() { // 获取当前时间戳(毫秒级) $timestamp = floor(microtime(true) * 1000); // 如果当前时间小于上次生成ID的时间戳,则抛出异常 if ($timestamp < $this->lastTimestamp) { throw new Exception("Invalid system clock!"); } // 如果当前时间戳与上次时间戳相同,则自增序列号 if ($timestamp == $this->lastTimestamp) { $this->sequence = ($this->sequence + 1) & $this->sequenceMask; // 如果序列号等于0,则需要进入下一毫秒重新生成ID if ($this->sequence == 0) { $timestamp = $this->waitNextMillis($this->lastTimestamp); } } else { $this->sequence = 0; } // 保存最后生成ID的时间戳 $this->lastTimestamp = $timestamp; // 生成最终的唯一ID $uniqueId = (($timestamp << $this->timestampLeftShift) | ($this->datacenterId << $this->datacenterIdShift) | ($this->workerId << $this->workerIdShift) | $this->sequence); return $uniqueId; } // 阻塞到下一个毫秒,直到获得新的时间戳 private function waitNextMillis($lastTimestamp) { $timestamp = floor(microtime(true) * 1000); while ($timestamp <= $lastTimestamp) { usleep(1000); $timestamp = floor(microtime(true) * 1000); } return $timestamp; } } // 测试方法 $snowflake = new Snowflake(1, 1); for ($i = 0; $i < 10; $i++) { $uniqueId = $snowflake->generateId(); echo $uniqueId . "\n"; } ?>
在上述代码中,我们创建了一个名为Snowflake
的类,该类用于生成Snowflake算法的唯一ID。它具有以下主要属性和方法:
__construct($workerId, $datacenterId)
:初始化Snowflake算法的参数,包括工作节点ID(workerId)和数据中心ID(datacenterId)。generateId()
:生成下一个唯一ID。waitNextMillis($lastTimestamp)
:阻塞到下一个毫秒,直到获得新的时间戳。
在测试方法中,我们创建了一个Snowflake
实例,并使用其generateId()
方法生成了10个唯一ID,并打印出来。