snowflow php实现

Snowflake PHP 实现
Snowflake 是一种分布式唯一 ID 生成算法,常用于分布式系统中生成全局唯一的 ID。以下是在 PHP 中实现 Snowflake 算法的步骤和代码示例。
理解 Snowflake 算法
Snowflake 算法生成的 ID 是一个 64 位的长整型,结构如下:
- 1 位符号位(始终为 0)
- 41 位时间戳(毫秒级)
- 10 位工作机器 ID(5 位数据中心 ID + 5 位机器 ID)
- 12 位序列号
PHP 实现代码
<?php
class Snowflake {
private $epoch = 1609459200000; // 自定义起始时间戳(2021-01-01 00:00:00 UTC)
private $workerIdBits = 5;
private $datacenterIdBits = 5;
private $sequenceBits = 12;
private $workerId;
private $datacenterId;
private $sequence = 0;
private $lastTimestamp = -1;
public function __construct($workerId, $datacenterId) {
$maxWorkerId = -1 ^ (-1 << $this->workerIdBits);
$maxDatacenterId = -1 ^ (-1 << $this->datacenterIdBits);
if ($workerId > $maxWorkerId || $workerId < 0) {
throw new Exception("Worker ID must be between 0 and $maxWorkerId");
}
if ($datacenterId > $maxDatacenterId || $datacenterId < 0) {
throw new Exception("Datacenter ID must be between 0 and $maxDatacenterId");
}
$this->workerId = $workerId;
$this->datacenterId = $datacenterId;
}
public function nextId() {
$timestamp = $this->timeGen();
if ($timestamp < $this->lastTimestamp) {
throw new Exception("Clock moved backwards. Refusing to generate ID");
}
if ($this->lastTimestamp == $timestamp) {
$this->sequence = ($this->sequence + 1) & ((-1 ^ (-1 << $this->sequenceBits)));
if ($this->sequence == 0) {
$timestamp = $this->tilNextMillis($this->lastTimestamp);
}
} else {
$this->sequence = 0;
}
$this->lastTimestamp = $timestamp;
return (($timestamp - $this->epoch) << ($this->workerIdBits + $this->datacenterIdBits + $this->sequenceBits))
| ($this->datacenterId << ($this->workerIdBits + $this->sequenceBits))
| ($this->workerId << $this->sequenceBits)
| $this->sequence;
}
private function timeGen() {
return floor(microtime(true) * 1000);
}
private function tilNextMillis($lastTimestamp) {
$timestamp = $this->timeGen();
while ($timestamp <= $lastTimestamp) {
$timestamp = $this->timeGen();
}
return $timestamp;
}
}
// 使用示例
$snowflake = new Snowflake(1, 1);
$id = $snowflake->nextId();
echo $id;
?>
代码说明
epoch是自定义的起始时间戳,用于减少生成的时间戳位数。workerId和datacenterId用于区分不同的工作机器和数据中心。nextId方法是核心逻辑,生成唯一的 ID。timeGen获取当前毫秒级时间戳。tilNextMillis在时间回拨时等待直到下一毫秒。
注意事项
- 确保
workerId和datacenterId在分布式系统中唯一。 - 时间回拨可能会导致 ID 重复,需要处理异常。
- 起始时间戳
epoch可以根据需要调整。
性能优化
- 可以使用 PHP 扩展(如
gmp)处理大整数运算。 - 在高并发场景下,可以考虑使用缓存或队列减少竞争。
测试验证
$snowflake = new Snowflake(1, 1);
for ($i = 0; $i < 10; $i++) {
echo $snowflake->nextId() . "\n";
}
运行测试代码,确保生成的 ID 唯一且递增。







