self::MAX_MACHINE_ID) { throw new \InvalidArgumentException("机器ID必须在0-" . self::MAX_MACHINE_ID . "之间"); } $this->machineId = $machineId; } /** * 生成ID * @return string */ public function generateId() { $timestamp = $this->getTimestamp(); if ($timestamp < $this->lastTimestamp) { throw new \Exception("时钟回拨异常"); } 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; } $this->lastTimestamp = $timestamp; return (($timestamp - self::EPOCH) << self::TIMESTAMP_SHIFT) | ($this->machineId << self::MACHINE_SHIFT) | $this->sequence; } /** * 获取当前毫秒时间戳 * @return int */ private function getTimestamp() { return (int)(microtime(true) * 1000); } /** * 等待下一毫秒 * @param int $lastTimestamp * @return int */ private function waitNextMillis($lastTimestamp) { $timestamp = $this->getTimestamp(); while ($timestamp <= $lastTimestamp) { usleep(100); // 休眠100微秒 $timestamp = $this->getTimestamp(); } return $timestamp; } /** * 解析ID * @param string $id * @return array */ public static function parseId($id) { $timestamp = ($id >> self::TIMESTAMP_SHIFT) + self::EPOCH; $machineId = ($id >> self::MACHINE_SHIFT) & self::MAX_MACHINE_ID; $sequence = $id & self::MAX_SEQUENCE; return [ 'timestamp' => $timestamp, 'machine_id' => $machineId, 'sequence' => $sequence, 'generate_time' => date('Y-m-d H:i:s', $timestamp / 1000) ]; } }