# 雪花算法的实现

``````<?php
class SnowFlake
{
const TWEPOCH = 0; // 时间起始标记点，作为基准，一般取系统的最近时间（一旦确定不能变动）

const WORKER_ID_BITS     = 5; // 机器标识位数
const DATACENTER_ID_BITS = 5; // 数据中心标识位数
const SEQUENCE_BITS      = 12; // 毫秒内自增位

private \$workerId; // 工作机器ID
private \$datacenterId; // 数据中心ID
private \$sequence; // 毫秒内序列

private \$maxWorkerId     = -1 ^ (-1 << self::WORKER_ID_BITS); // 机器ID最大值
private \$maxDatacenterId = -1 ^ (-1 << self::DATACENTER_ID_BITS); // 数据中心ID最大值

private \$workerIdShift      = self::SEQUENCE_BITS; // 机器ID偏左移位数
private \$datacenterIdShift  = self::SEQUENCE_BITS + self::WORKER_ID_BITS; // 数据中心ID左移位数
private \$timestampLeftShift = self::SEQUENCE_BITS + self::WORKER_ID_BITS + self::DATACENTER_ID_BITS; // 时间毫秒左移位数
private \$sequenceMask       = -1 ^ (-1 << self::SEQUENCE_BITS); // 生成序列的掩码

private \$lastTimestamp = -1; // 上次生产id时间戳

public function __construct(\$workerId, \$datacenterId, \$sequence = 0)
{
if (\$workerId > \$this->maxWorkerId || \$workerId < 0) {
throw new Exception("worker Id can't be greater than {\$this->maxWorkerId} or less than 0");
}

if (\$datacenterId > \$this->maxDatacenterId || \$datacenterId < 0) {
throw new Exception("datacenter Id can't be greater than {\$this->maxDatacenterId} or less than 0");
}

\$this->workerId     = \$workerId;
\$this->datacenterId = \$datacenterId;
\$this->sequence     = \$sequence;
}

public function createId()
{
\$timestamp = \$this->createTimestamp();

if (\$timestamp < \$this->lastTimestamp) {//当产生的时间戳小于上次的生成的时间戳时，报错
\$diffTimestamp = bcsub(\$this->lastTimestamp, \$timestamp);
throw new Exception("Clock moved backwards.  Refusing to generate id for {\$diffTimestamp} milliseconds");
}

if (\$this->lastTimestamp == \$timestamp) {//当生成的时间戳等于上次生成的时间戳的时候
\$this->sequence = (\$this->sequence + 1) & \$this->sequenceMask;//序列自增一次

if (0 == \$this->sequence) {//当序列为0时，重新生成最新的时间戳
\$timestamp = \$this->createNextTimestamp(\$this->lastTimestamp);
}
} else {//当生成的时间戳不等于上次的生成的时间戳的时候，序列归0
\$this->sequence = 0;
}

\$this->lastTimestamp = \$timestamp;

return ((\$timestamp - self::TWEPOCH) << \$this->timestampLeftShift) |
(\$this->datacenterId << \$this->datacenterIdShift) |
(\$this->workerId << \$this->workerIdShift) |
\$this->sequence;
}

protected function createNextTimestamp(\$lastTimestamp) //生成一个大于等于 上次生成的时间戳 的时间戳
{
\$timestamp = \$this->createTimestamp();
while (\$timestamp <= \$lastTimestamp) {
\$timestamp = \$this->createTimestamp();
}

return \$timestamp;
}

protected function createTimestamp()//生成毫秒级别的时间戳
{
return floor(microtime(true) * 1000);
}
}
?>``````

(=￣ω￣=)··· 暂无内容！

4

0

6

3