PHP 实现雪花算法生成ID
·
<?php
class Snowflake
{
const EPOCH = 1609459200000; // 自定义纪元时间:2021-01-01 00:00:00 UTC(毫秒)
const TIMESTAMP_BITS = 41;
const DATA_CENTER_BITS = 5;
const MACHINE_BITS = 5;
const SEQUENCE_BITS = 12;
const MAX_DATA_CENTER_ID = (1 << self::DATA_CENTER_BITS) - 1; // 31
const MAX_MACHINE_ID = (1 << self::MACHINE_BITS) - 1; // 31
const MAX_SEQUENCE = (1 << self::SEQUENCE_BITS) - 1; // 4095
private $dataCenterId;
private $machineId;
private $sequence = 0;
private $lastTimestamp = 0;
public function __construct($dataCenterId = 0, $machineId = 0)
{
if ($dataCenterId > self::MAX_DATA_CENTER_ID || $dataCenterId < 0) {
throw new InvalidArgumentException("Data center ID can't be greater than " . self::MAX_DATA_CENTER_ID);
}
if ($machineId > self::MAX_MACHINE_ID || $machineId < 0) {
throw new InvalidArgumentException("Machine ID can't be greater than " . self::MAX_MACHINE_ID);
}
$this->dataCenterId = $dataCenterId;
$this->machineId = $machineId;
}
/**
* 生成唯一ID
*/
public function nextId(): int
{
$timestamp = $this->timeGen();
// 防止时钟回拨
if ($timestamp < $this->lastTimestamp) {
throw new RuntimeException("Clock moved backwards. Refusing to generate ID.");
}
// 同一毫秒内:序列号递增
if ($timestamp === $this->lastTimestamp) {
$this->sequence = ($this->sequence + 1) & self::MAX_SEQUENCE;
if ($this->sequence === 0) {
// 等待下一毫秒
$timestamp = $this->tilNextMillis($this->lastTimestamp);
}
} else {
$this->sequence = 0; // 新毫秒,序列重置
}
$this->lastTimestamp = $timestamp;
$timestamp -= self::EPOCH;
// 组合64位ID
return ($timestamp << (self::DATA_CENTER_BITS + self::MACHINE_BITS + self::SEQUENCE_BITS))
| ($this->dataCenterId << (self::MACHINE_BITS + self::SEQUENCE_BITS))
| ($this->machineId << self::SEQUENCE_BITS)
| $this->sequence;
}
/**
* 阻塞到下一个毫秒
*/
private function tilNextMillis($lastTimestamp)
{
$timestamp = $this->timeGen();
while ($timestamp <= $lastTimestamp) {
$timestamp = $this->timeGen();
}
return $timestamp;
}
/**
* 获取当前时间戳(毫秒)
*/
private function timeGen(): int
{
return (int)(microtime(true) * 1000);
}
/**
* 解析 Snowflake ID(调试用)
*/
public function parseId(int $id): array
{
$sequence = $id & self::MAX_SEQUENCE;
$machineId = ($id >> self::SEQUENCE_BITS) & self::MAX_MACHINE_ID;
$dataCenterId = ($id >> (self::SEQUENCE_BITS + self::MACHINE_BITS)) & self::MAX_DATA_CENTER_ID;
$timestamp = ($id >> (self::SEQUENCE_BITS + self::MACHINE_BITS + self::DATA_CENTER_BITS)) + self::EPOCH;
return [
'timestamp' => $timestamp,
'datetime' => date('Y-m-d H:i:s.v', $timestamp / 1000),
'data_center_id' => $dataCenterId,
'machine_id' => $machineId,
'sequence' => $sequence,
];
}
}
// 创建 Snowflake 实例(数据中心ID=1,机器ID=1)
$snowflake = new Snowflake(1, 1);
// 生成多个 ID
for ($i = 0; $i < 5; $i++) {
$id = $snowflake->nextId();
echo $id . "\n";
usleep(1000); // 延迟1毫秒,避免序列号冲突
}
?>
更多推荐



所有评论(0)