不同AI生成的PHP版雪花算法

OpenAI

php 复制代码
<?php
/**
 * Snowflake 雪花算法生成器
 * 生成的 64 位 ID 结构:
 *  1 位    保留位(始终为0,防止负数)
 *  41 位   时间戳(毫秒级,当前时间减去自定义纪元)
 *  5 位    数据中心ID
 *  5 位    机器ID
 *  12 位   序列号(同一毫秒内生成多个 ID)
 */
class Snowflake
{
    // 自定义纪元(起始时间戳),可根据实际情况调整
    private $twepoch = 1288834974657;

    // 各部分占用的位数
    private $workerIdBits     = 5;   // 机器ID位数
    private $datacenterIdBits = 5;   // 数据中心ID位数
    private $sequenceBits     = 12;  // 序列号位数

    // 各部分的最大数值(通过位运算计算)
    private $maxWorkerId;
    private $maxDatacenterId;
    private $sequenceMask;

    // 各部分左移位数
    private $workerIdShift;
    private $datacenterIdShift;
    private $timestampLeftShift;

    // 工作机器ID和数据中心ID(取值范围 0 ~ 最大值)
    private $workerId;
    private $datacenterId;

    // 序列号,记录同一毫秒内生成的ID序号
    private $sequence = 0;

    // 上一次生成ID的时间戳,初始化为 -1
    private $lastTimestamp = -1;

    /**
     * 构造函数
     *
     * @param int $workerId      机器ID(0 ~ 31)
     * @param int $datacenterId  数据中心ID(0 ~ 31)
     */
    public function __construct($workerId, $datacenterId)
    {
        // 计算各部分最大值:如 -1 << 5 得到 0b11111 (31)
        $this->maxWorkerId     = -1 ^ (-1 << $this->workerIdBits);
        $this->maxDatacenterId = -1 ^ (-1 << $this->datacenterIdBits);
        // 序列号最大值(4095:12位全1)
        $this->sequenceMask    = -1 ^ (-1 << $this->sequenceBits);

        // 检查传入的机器ID和数据中心ID是否合法
        if ($workerId > $this->maxWorkerId || $workerId < 0) {
            throw new Exception("机器ID必须在 0 到 " . $this->maxWorkerId . " 之间");
        }
        if ($datacenterId > $this->maxDatacenterId || $datacenterId < 0) {
            throw new Exception("数据中心ID必须在 0 到 " . $this->maxDatacenterId . " 之间");
        }
        $this->workerId     = $workerId;
        $this->datacenterId = $datacenterId;

        // 计算各部分需要左移的位数
        // 序列号占用 12 位,因此机器ID需要左移 12 位
        $this->workerIdShift     = $this->sequenceBits;
        // 数据中心ID需要左移 12 + 5 = 17 位
        $this->datacenterIdShift = $this->sequenceBits + $this->workerIdBits;
        // 时间戳需要左移 12 + 5 + 5 = 22 位
        $this->timestampLeftShift = $this->sequenceBits + $this->workerIdBits + $this->datacenterIdBits;
    }

    /**
     * 生成下一个唯一ID
     *
     * @return int 64位的唯一ID
     */
    public function nextId()
    {
        // 获取当前毫秒级时间戳
        $timestamp = $this->timeGen();

        // 如果当前时间小于上一次生成ID的时间戳,则说明系统时钟回拨,无法生成ID
        if ($timestamp < $this->lastTimestamp) {
            throw new Exception("时钟回拨异常,拒绝生成ID. 差值: " . ($this->lastTimestamp - $timestamp) . " 毫秒");
        }

        // 如果当前时间与上次生成ID时间相同,表示同一毫秒内生成多个ID
        if ($timestamp == $this->lastTimestamp) {
            // 序列号自增,并通过位运算确保在 12 位内(最大值为 4095)
            $this->sequence = ($this->sequence + 1) & $this->sequenceMask;
            // 如果序列号达到最大值,则等待下一毫秒
            if ($this->sequence == 0) {
                $timestamp = $this->tilNextMillis($this->lastTimestamp);
            }
        } else {
            // 不同毫秒内,序列号重置为 0
            $this->sequence = 0;
        }

        // 更新上一次生成ID的时间戳
        $this->lastTimestamp = $timestamp;

        /**
         * 拼接各部分生成最终ID:
         * 1. (当前时间戳 - 自定义纪元) 左移 TIMESTAMP_LEFT_SHIFT 位
         * 2. 数据中心ID左移 DATACENTER_ID_SHIFT 位
         * 3. 机器ID左移 WORKER_ID_SHIFT 位
         * 4. 序列号(低12位)
         * 最终通过按位或(|)运算组合成一个 64 位的整数
         */
        $id = (($timestamp - $this->twepoch) << $this->timestampLeftShift)
            | ($this->datacenterId << $this->datacenterIdShift)
            | ($this->workerId << $this->workerIdShift)
            | $this->sequence;

        return $id;
    }

    /**
     * 等待直到下一毫秒
     *
     * @param int $lastTimestamp 上次生成ID的时间戳
     * @return int 下一毫秒的时间戳
     */
    private function tilNextMillis($lastTimestamp)
    {
        $timestamp = $this->timeGen();
        // 循环等待直到时间戳发生变化(进入下一毫秒)
        while ($timestamp <= $lastTimestamp) {
            $timestamp = $this->timeGen();
        }
        return $timestamp;
    }

    /**
     * 获取当前时间戳(毫秒级)
     *
     * @return int 当前毫秒级时间戳
     */
    private function timeGen()
    {
        // microtime(true) 返回秒为单位的小数,将其乘以 1000 转换为毫秒
        return (int) (microtime(true) * 1000);
    }
}

// ------------------------- 测试示例 ------------------------- //

// 创建一个 Snowflake 实例,指定机器ID和数据中心ID
try {
    $snowflake = new Snowflake(1, 1);

    // 生成 10 个唯一ID,并输出
    for ($i = 0; $i < 10; $i++) {
        echo "生成的ID " . ($i + 1) . " : " . $snowflake->nextId() . "\n";
    }
} catch (Exception $e) {
    echo "异常:" . $e->getMessage();
}
?>

DeepSeek

php 复制代码
<?php

/**
 * 雪花算法分布式ID生成器
 * 结构:0 | 时间戳(41位) | 数据中心ID(5位) | 机器ID(5位) | 序列号(12位)
 */
class Snowflake
{
    // 起始时间戳(2024-01-01 00:00:00 UTC)
    const EPOCH = 1704067200000;
    
    // 位数分配
    const SEQUENCE_BITS = 12;   // 序列号位数
    const MACHINE_BITS = 5;     // 机器标识位数
    const DATACENTER_BITS = 5;  // 数据中心位数

    // 最大值计算(位运算优化)
    const MAX_SEQUENCE = -1 ^ (-1 << self::SEQUENCE_BITS);
    const MAX_MACHINE = -1 ^ (-1 << self::MACHINE_BITS);
    const MAX_DATACENTER = -1 ^ (-1 << self::DATACENTER_BITS);

    // 移位偏移量计算
    const TIMESTAMP_SHIFT = self::SEQUENCE_BITS + self::MACHINE_BITS + self::DATACENTER_BITS;
    const DATACENTER_SHIFT = self::SEQUENCE_BITS + self::MACHINE_BITS;
    const MACHINE_SHIFT = self::SEQUENCE_BITS;

    private $machineId;      // 机器标识ID
    private $datacenterId;   // 数据中心ID
    private $sequence = 0;   // 序列号
    private $lastTimestamp = -1; // 上次生成时间戳

    /**
     * 构造函数
     * @param int $machineId    机器ID (0~31)
     * @param int $datacenterId 数据中心ID (0~31)
     */
    public function __construct($machineId, $datacenterId)
    {
        // 参数校验
        if ($machineId > self::MAX_MACHINE || $machineId < 0) {
            throw new InvalidArgumentException("机器ID值超出范围(0~".self::MAX_MACHINE.")");
        }
        if ($datacenterId > self::MAX_DATACENTER || $datacenterId < 0) {
            throw new InvalidArgumentException("数据中心ID值超出范围(0~".self::MAX_DATACENTER.")");
        }
        
        $this->machineId = $machineId;
        $this->datacenterId = $datacenterId;
    }

    /**
     * 生成下一个分布式ID
     * @return int 64位整型ID(PHP中实际返回字符串类型以保证精度)
     */
    public function generateId()
    {
        $timestamp = $this->getCurrentTimestamp();

        // 时钟回拨检查
        if ($timestamp < $this->lastTimestamp) {
            $diff = $this->lastTimestamp - $timestamp;
            throw new RuntimeException("系统时钟回拨 {$diff} 毫秒");
        }

        // 同一毫秒内生成
        if ($this->lastTimestamp == $timestamp) {
            $this->sequence = ($this->sequence + 1) & self::MAX_SEQUENCE;
            
            // 序列号耗尽,等待下一毫秒
            if ($this->sequence == 0) {
                $timestamp = $this->waitNextMillis($this->lastTimestamp);
            }
        } else {
            // 新时间戳重置序列号
            $this->sequence = 0;
        }

        $this->lastTimestamp = $timestamp;

        // 组合各部分数据
        $id = (($timestamp) << self::TIMESTAMP_SHIFT)
            | ($this->datacenterId << self::DATACENTER_SHIFT)
            | ($this->machineId << self::MACHINE_SHIFT)
            | $this->sequence;

        // 返回字符串类型以避免32位系统精度丢失
        return (string)$id;
    }

    /**
     * 阻塞到下一毫秒
     * @param int $lastTimestamp 上次生成时间戳
     * @return int 当前时间戳
     */
    private function waitNextMillis($lastTimestamp)
    {
        $timestamp = $this->getCurrentTimestamp();
        while ($timestamp <= $lastTimestamp) {
            usleep(1000); // 休眠1毫秒
            $timestamp = $this->getCurrentTimestamp();
        }
        return $timestamp;
    }

    /**
     * 获取当前时间戳(毫秒)
     * @return int 毫秒时间戳
     */
    private function getCurrentTimestamp()
    {
        return round(microtime(true) * 1000) - self::EPOCH;
    }
}

/* 使用示例 */
try {
    $snowflake = new Snowflake(1, 1); // 机器ID=1,数据中心ID=1
    
    // 生成10个ID
    for ($i = 0; $i < 10; $i++) {
        echo $snowflake->generateId() . PHP_EOL;
    }
} catch (Exception $e) {
    echo $e->getMessage();
}

Kimi

php 复制代码
<?php

/**
 * 雪花算法生成唯一ID
 * 基于Twitter的Snowflake算法,生成一个64位的唯一ID
 */
class Snowflake
{
    // 以下是各个部分所占的位数
    const SIGN_BIT = 1; // 符号位,始终为0
    const TIMESTAMP_BIT = 41; // 时间戳位数
    const DATA_CENTER_ID_BIT = 5; // 数据中心ID位数
    const WORKER_ID_BIT = 5; // 机器节点ID位数
    const SEQUENCE_BIT = 12; // 序列号位数

    // 最大值
    const MAX_DATA_CENTER_ID = -1 ^ (-1 << self::DATA_CENTER_ID_BIT); // 31
    const MAX_WORKER_ID = -1 ^ (-1 << self::WORKER_ID_BIT); // 31
    const MAX_SEQUENCE = -1 ^ (-1 << self::SEQUENCE_BIT); // 4095

    // 每一部分的偏移量
    const DATA_CENTER_ID_SHIFT = self::SEQUENCE_BIT;
    const WORKER_ID_SHIFT = self::SEQUENCE_BIT + self::DATA_CENTER_ID_BIT;
    const TIMESTAMP_SHIFT = self::SEQUENCE_BIT + self::DATA_CENTER_ID_BIT + self::WORKER_ID_BIT;

    // 开始时间戳(2023-01-01 00:00:00的毫秒数)
    const EPOCH = 1672502400000;

    // 数据中心ID和机器节点ID
    private $dataCenterId;
    private $workerId;

    // 序列号
    private $sequence = 0;

    // 上一次的时间戳
    private $lastTimestamp = -1;

    /**
     * 构造函数
     * @param int $dataCenterId 数据中心ID
     * @param int $workerId 机器节点ID
     */
    public function __construct($dataCenterId = 0, $workerId = 0)
    {
        if ($dataCenterId > self::MAX_DATA_CENTER_ID || $dataCenterId < 0) {
            throw new \InvalidArgumentException("dataCenterId不能大于" . self::MAX_DATA_CENTER_ID . "或小于0");
        }
        if ($workerId > self::MAX_WORKER_ID || $workerId < 0) {
            throw new \InvalidArgumentException("workerId不能大于" . self::MAX_WORKER_ID . "或小于0");
        }
        $this->dataCenterId = $dataCenterId;
        $this->workerId = $workerId;
    }

    /**
     * 生成唯一ID
     * @return int 唯一ID
     */
    public function generateId()
    {
        $currentTimestamp = $this->getCurrentTimestamp();
        if ($currentTimestamp < $this->lastTimestamp) {
            throw new \RuntimeException("时间戳回退,拒绝生成ID");
        }

        if ($currentTimestamp == $this->lastTimestamp) {
            $this->sequence = ($this->sequence + 1) & self::MAX_SEQUENCE;
            if ($this->sequence == 0) {
                $currentTimestamp = $this->tilNextMillis($this->lastTimestamp);
            }
        } else {
            $this->sequence = 0;
        }

        $this->lastTimestamp = $currentTimestamp;

        // ID拼接
        $id = (($currentTimestamp - self::EPOCH) << self::TIMESTAMP_SHIFT)
            | ($this->dataCenterId << self::DATA_CENTER_ID_SHIFT)
            | ($this->workerId << self::WORKER_ID_SHIFT)
            | $this->sequence;

        return $id;
    }

    /**
     * 等待下一毫秒
     * @param int $lastTimestamp 上一次的时间戳
     * @return int 当前时间戳
     */
    private function tilNextMillis($lastTimestamp)
    {
        $timestamp = $this->getCurrentTimestamp();
        while ($timestamp <= $lastTimestamp) {
            $timestamp = $this->getCurrentTimestamp();
        }
        return $timestamp;
    }

    /**
     * 获取当前时间戳(毫秒)
     * @return int 当前时间戳
     */
    private function getCurrentTimestamp()
    {
        return round(microtime(true) * 1000);
    }
}

// 使用示例
$snowflake = new Snowflake(1, 2); // 数据中心ID为1,机器节点ID为2
$id = $snowflake->generateId();
echo $id;

智谱清言

php 复制代码
<?php

/**
 * Snowflake ID生成类,基于Twitter的Snowflake算法
 */
class Snowflake {
    // 雪花算法常量定义
    const EPOCH = 1288834974657; // 起始时间戳,单位毫秒
    const DATA_CENTER_ID_BITS = 5; // 数据中心ID所占的位数
    const MACHINE_ID_BITS = 5; // 机器ID所占的位数
    const SEQUENCE_BITS = 12; // 序列号所占的位数

    const MAX_DATA_CENTER_ID = (1 << self::DATA_CENTER_ID_BITS) - 1; // 最大的数据中心ID
    const MAX_MACHINE_ID = (1 << self::MACHINE_ID_BITS) - 1; // 最大的机器ID
    const MAX_SEQUENCE = (1 << self::SEQUENCE_BITS) - 1; // 最大的序列号

    const MACHINE_ID_SHIFT = self::SEQUENCE_BITS; // 机器ID的偏移量
    const DATA_CENTER_ID_SHIFT = self::MACHINE_ID_SHIFT + self::MACHINE_ID_BITS; // 数据中心ID的偏移量
    const TIMESTAMP_SHIFT = self::DATA_CENTER_ID_SHIFT + self::DATA_CENTER_ID_BITS; // 时间戳的偏移量

    private $dataCenterId; // 数据中心ID
    private $machineId; // 机器ID
    private $sequence = 0; // 序列号
    private $lastTimestamp = -1; // 上一次生成ID的时间戳

    /**
     * 构造函数
     * @param int $dataCenterId 数据中心ID,范围0到31
     * @param int $machineId 机器ID,范围0到31
     */
    public function __construct($dataCenterId,$machineId) {
        if ($dataCenterId < 0 ||$dataCenterId > self::MAX_DATA_CENTER_ID) {
            throw new InvalidArgumentException("数据中心ID必须在0和" . self::MAX_DATA_CENTER_ID . "之间");
        }
        if ($machineId < 0 ||$machineId > self::MAX_MACHINE_ID) {
            throw new InvalidArgumentException("机器ID必须在0和" . self::MAX_MACHINE_ID . "之间");
        }
        $this->dataCenterId =$dataCenterId;
        $this->machineId =$machineId;
    }

    /**
     * 生成下一个ID
     * @return string 生成的ID字符串
     */
    public function nextId() {
        $timestamp =$this->timeGen();

        // 如果当前时间戳小于上一次的时间戳,说明时钟回拨
        if ($timestamp <$this->lastTimestamp) {
            throw new RuntimeException("时钟回拨,拒绝生成ID");
        }

        // 如果当前时间戳与上一次的时间戳相同,同一毫秒内生成多个ID
        if ($timestamp ==$this->lastTimestamp) {
            $this->sequence = ($this->sequence + 1) & self::MAX_SEQUENCE;
            // 如果序列号达到最大值,等待下一毫秒
            if ($this->sequence == 0) {
                $timestamp =$this->tilNextMillis($this->lastTimestamp);
            }
        } else {
            // 如果进入新的毫秒,序列号重置为0
            $this->sequence = 0;
        }

        // 更新上一次的时间戳
        $this->lastTimestamp =$timestamp;

        // 生成ID
        $id = (($timestamp - self::EPOCH) << self::TIMESTAMP_SHIFT) |
              ($this->dataCenterId << self::DATA_CENTER_ID_SHIFT) |
              ($this->machineId << self::MACHINE_ID_SHIFT) |
              $this->sequence;

        return strval($id);
    }

    /**
     * 获取当前时间戳,单位毫秒
     * @return int
     */
    private function timeGen() {
        return floor(microtime(true) * 1000);
    }

    /**
     * 等待下一毫秒,直到时间戳增加
     * @param int $lastTimestamp 上一次的时间戳
     * @return int 当前时间戳
     */
    private function tilNextMillis($lastTimestamp) {
        $timestamp =$this->timeGen();
        while ($timestamp <=$lastTimestamp) {
            $timestamp =$this->timeGen();
        }
        return $timestamp;
    }
}

// 使用示例
try {
    // 创建Snowflake实例,数据中心ID为1,机器ID为1
    $snowflake = new Snowflake(1, 1);

    // 生成并输出10个唯一ID
    for ($i = 0;$i < 10; $i++) {
        $id =$snowflake->nextId();
        echo $id . "\n";
    }

    // 创建另一个Snowflake实例,数据中心ID为1,机器ID为2
    $snowflake2 = new Snowflake(1, 2);

    // 生成并输出10个唯一ID
    for ($i = 0;$i < 10; $i++) {
        $id =$snowflake2->nextId();
        echo $id . "\n";
    }

    // 创建另一个Snowflake实例,数据中心ID为2,机器ID为1
    $snowflake3 = new Snowflake(2, 1);

    // 生成并输出10个唯一ID
    for ($i = 0;$i < 10; $i++) {
        $id =$snowflake3->nextId();
        echo $id . "\n";
    }
} catch (Exception $e) {
    echo "错误: " . $e->getMessage() . "\n";
}

Claude

php 复制代码
<?php

/**
 * 雪花算法(Snowflake)PHP实现
 * 
 * 雪花算法是由Twitter开发的分布式ID生成算法,能够在分布式系统中产生唯一的ID
 * 该算法生成的ID结构为64位长整型,由以下部分组成:
 * 1. 1位符号位,固定为0(表示正数)
 * 2. 41位时间戳(毫秒级),可使用约69年
 * 3. 10位工作机器ID,包括5位数据中心ID和5位机器ID,最多支持32个数据中心和每个中心下32台机器
 * 4. 12位序列号,1毫秒内最多生成4096个ID
 */
class Snowflake {
    /**
     * 开始时间戳(2020-01-01)
     * 这是算法的基准时间,用于计算相对时间戳
     */
    const START_TIMESTAMP = 1577808000000; // 2020-01-01 00:00:00 GMT
    
    /**
     * 各部分占用的位数
     */
    const SEQUENCE_BITS = 12;       // 序列号占用的位数
    const MACHINE_ID_BITS = 5;      // 机器ID占用的位数
    const DATACENTER_ID_BITS = 5;   // 数据中心ID占用的位数
    
    /**
     * 各部分的最大值
     */
    const MAX_SEQUENCE = -1 ^ (-1 << self::SEQUENCE_BITS);          // 序列号最大值 4095
    const MAX_MACHINE_ID = -1 ^ (-1 << self::MACHINE_ID_BITS);      // 机器ID最大值 31
    const MAX_DATACENTER_ID = -1 ^ (-1 << self::DATACENTER_ID_BITS);// 数据中心ID最大值 31
    
    /**
     * 各部分向左的位移
     */
    const MACHINE_ID_SHIFT = self::SEQUENCE_BITS;                                   // 机器ID向左移12位
    const DATACENTER_ID_SHIFT = self::SEQUENCE_BITS + self::MACHINE_ID_BITS;        // 数据中心ID向左移17位
    const TIMESTAMP_SHIFT = self::SEQUENCE_BITS + self::MACHINE_ID_BITS + self::DATACENTER_ID_BITS; // 时间戳向左移22位
    
    /**
     * 数据中心ID
     * @var int
     */
    private $datacenterId;
    
    /**
     * 机器ID
     * @var int
     */
    private $machineId;
    
    /**
     * 毫秒内序列号
     * @var int
     */
    private $sequence = 0;
    
    /**
     * 上次生成ID的时间戳
     * @var int
     */
    private $lastTimestamp = -1;
    
    /**
     * 构造函数
     * 
     * @param int $datacenterId 数据中心ID (0~31)
     * @param int $machineId 机器ID (0~31)
     * @throws Exception 当数据中心ID或机器ID超出范围时抛出异常
     */
    public function __construct($datacenterId, $machineId) {
        // 参数校验
        if ($datacenterId > self::MAX_DATACENTER_ID || $datacenterId < 0) {
            throw new Exception("数据中心ID不能大于".self::MAX_DATACENTER_ID."或小于0");
        }
        
        if ($machineId > self::MAX_MACHINE_ID || $machineId < 0) {
            throw new Exception("机器ID不能大于".self::MAX_MACHINE_ID."或小于0");
        }
        
        $this->datacenterId = $datacenterId;
        $this->machineId = $machineId;
    }
    
    /**
     * 获取当前时间戳(毫秒)
     * 
     * @return int 当前时间戳(毫秒)
     */
    private function getCurrentTimestamp() {
        // 获取当前时间戳,单位为毫秒
        return floor(microtime(true) * 1000);
    }
    
    /**
     * 阻塞到下一个毫秒,直到获得新的时间戳
     * 
     * @param int $lastTimestamp 上次生成ID的时间戳
     * @return int 新的时间戳
     */
    private function waitNextMillis($lastTimestamp) {
        $timestamp = $this->getCurrentTimestamp();
        while ($timestamp <= $lastTimestamp) {
            $timestamp = $this->getCurrentTimestamp();
        }
        return $timestamp;
    }
    
    /**
     * 生成ID
     * 
     * @return string 返回生成的ID(字符串形式,因为PHP整数范围有限)
     * @throws Exception 当时钟回拨时抛出异常
     */
    public function nextId() {
        // 获取当前时间戳
        $timestamp = $this->getCurrentTimestamp();
        
        // 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过,抛出异常
        if ($timestamp < $this->lastTimestamp) {
            throw new Exception("时钟向后移动,拒绝生成ID,时间差: " . ($this->lastTimestamp - $timestamp) . " 毫秒");
        }
        
        // 如果是同一时间生成的,则进行毫秒内序列号递增
        if ($timestamp == $this->lastTimestamp) {
            // 序列号递增
            $this->sequence = ($this->sequence + 1) & self::MAX_SEQUENCE;
            // 同一毫秒内序列号已经达到最大值,阻塞到下一个毫秒
            if ($this->sequence == 0) {
                $timestamp = $this->waitNextMillis($this->lastTimestamp);
            }
        } else {
            // 时间戳改变,毫秒内序列号重置为0
            $this->sequence = 0;
        }
        
        // 记录上次生成ID的时间戳
        $this->lastTimestamp = $timestamp;
        
        // 计算相对时间戳(与起始时间的差值)
        $relativeTimestamp = $timestamp - self::START_TIMESTAMP;
        
        // 组装ID并返回
        // 使用字符串拼接,避免PHP整数溢出问题
        $id = (($relativeTimestamp << self::TIMESTAMP_SHIFT) |
               ($this->datacenterId << self::DATACENTER_ID_SHIFT) |
               ($this->machineId << self::MACHINE_ID_SHIFT) |
               $this->sequence);
        
        // 转换为字符串,避免潜在的整数溢出问题
        return (string)$id;
    }
}

// 使用示例
try {
    // 创建一个雪花算法实例,参数为数据中心ID和机器ID
    $snowflake = new Snowflake(1, 1);
    
    // 生成ID
    $id = $snowflake->nextId();
    echo "生成的ID: " . $id . PHP_EOL;
    
    // 批量生成多个ID
    echo "批量生成5个ID:" . PHP_EOL;
    for ($i = 0; $i < 5; $i++) {
        echo $snowflake->nextId() . PHP_EOL;
    }
} catch (Exception $e) {
    echo "错误: " . $e->getMessage() . PHP_EOL;
}
?>

豆包

php 复制代码
<?php

class Snowflake {
    // 起始时间戳,一般设置为项目开始的时间,单位:毫秒
    const EPOCH = 1609459200000; 

    // 数据中心 ID 所占的位数
    const DATA_CENTER_ID_BITS = 5; 
    // 机器 ID 所占的位数
    const WORKER_ID_BITS = 5; 
    // 序列号所占的位数
    const SEQUENCE_BITS = 12; 

    // 数据中心 ID 最大值
    const MAX_DATA_CENTER_ID = -1 ^ (-1 << self::DATA_CENTER_ID_BITS); 
    // 机器 ID 最大值
    const MAX_WORKER_ID = -1 ^ (-1 << self::WORKER_ID_BITS); 
    // 序列号最大值
    const MAX_SEQUENCE = -1 ^ (-1 << self::SEQUENCE_BITS); 

    // 机器 ID 向左移位数
    const WORKER_ID_SHIFT = self::SEQUENCE_BITS; 
    // 数据中心 ID 向左移位数
    const DATA_CENTER_ID_SHIFT = self::SEQUENCE_BITS + self::WORKER_ID_BITS; 
    // 时间戳向左移位数
    const TIMESTAMP_LEFT_SHIFT = self::SEQUENCE_BITS + self::WORKER_ID_BITS + self::DATA_CENTER_ID_BITS; 

    // 数据中心 ID
    private $dataCenterId; 
    // 机器 ID
    private $workerId; 
    // 序列号
    private $sequence = 0; 
    // 上一次生成 ID 的时间戳
    private $lastTimestamp = -1; 

    /**
     * 构造函数,初始化数据中心 ID 和机器 ID
     *
     * @param int $dataCenterId 数据中心 ID
     * @param int $workerId 机器 ID
     * @throws Exception 如果数据中心 ID 或机器 ID 超出范围,抛出异常
     */
    public function __construct($dataCenterId, $workerId) {
        // 检查数据中心 ID 是否在合法范围内
        if ($dataCenterId > self::MAX_DATA_CENTER_ID || $dataCenterId < 0) {
            throw new Exception("Data center ID must be between 0 and " . self::MAX_DATA_CENTER_ID);
        }
        // 检查机器 ID 是否在合法范围内
        if ($workerId > self::MAX_WORKER_ID || $workerId < 0) {
            throw new Exception("Worker ID must be between 0 and " . self::MAX_WORKER_ID);
        }

        $this->dataCenterId = $dataCenterId;
        $this->workerId = $workerId;
    }

    /**
     * 生成下一个唯一的 ID
     *
     * @return int 生成的唯一 ID
     * @throws Exception 如果系统时钟回拨,抛出异常
     */
    public function nextId() {
        // 获取当前时间戳,单位:毫秒
        $timestamp = $this->getCurrentTimestamp();

        // 处理时钟回拨问题
        if ($timestamp < $this->lastTimestamp) {
            throw new Exception("Clock moved backwards. Refusing to generate id for " . ($this->lastTimestamp - $timestamp) . " milliseconds");
        }

        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;
        }

        // 更新上一次生成 ID 的时间戳
        $this->lastTimestamp = $timestamp;

        // 生成最终的 ID
        return (($timestamp - self::EPOCH) << self::TIMESTAMP_LEFT_SHIFT) |
            ($this->dataCenterId << self::DATA_CENTER_ID_SHIFT) |
            ($this->workerId << self::WORKER_ID_SHIFT) |
            $this->sequence;
    }

    /**
     * 获取当前时间戳,单位:毫秒
     *
     * @return int 当前时间戳
     */
    private function getCurrentTimestamp() {
        return floor(microtime(true) * 1000);
    }

    /**
     * 等待下一毫秒
     *
     * @param int $lastTimestamp 上一次生成 ID 的时间戳
     * @return int 下一毫秒的时间戳
     */
    private function waitNextMillis($lastTimestamp) {
        $timestamp = $this->getCurrentTimestamp();
        while ($timestamp <= $lastTimestamp) {
            $timestamp = $this->getCurrentTimestamp();
        }
        return $timestamp;
    }
}

// 使用示例
try {
    // 创建 Snowflake 实例,指定数据中心 ID 和机器 ID
    $snowflake = new Snowflake(1, 1);
    // 生成唯一 ID
    $id = $snowflake->nextId();
    echo "Generated ID: " . $id;
} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}

腾讯元宝

php 复制代码
<?php
class Snowflake
{
    // 数据中心ID所占位数(5位,支持32个数据中心)
    const DATA_CENTER_ID_BITS = 5;
    // 机器ID所占位数(5位,支持32台机器)
    const MACHINE_ID_BITS = 5;
    // 序列号所占位数(12位,每毫秒支持4096个ID)
    const SEQUENCE_BITS = 12;

    // 最大数据中心ID(2^5 - 1)
    const MAX_DATA_CENTER_ID = -1 ^ (-1 << self::DATA_CENTER_ID_BITS);
    // 最大机器ID(2^5 - 1)
    const MAX_MACHINE_ID = -1 ^ (-1 << self::MACHINE_ID_BITS);

    // 时间戳左移位数(41+5+5=51位)
    const TIMESTAMP_LEFT_SHIFT = self::SEQUENCE_BITS + self::MACHINE_ID_BITS + self::DATA_CENTER_ID_BITS;
    // 机器ID左移位数(41+5=46位)
    const SEQUENCE_LEFT_SHIFT = self::MACHINE_ID_BITS + self::DATA_CENTER_ID_BITS;

    // 起始时间戳(2021-01-01 00:00:00,可自定义)
    private $epoch = 1609430400000;

    // 实例属性
    private int $datacenterId;    // 数据中心ID
    private int $machineId;       // 机器ID
    private int $sequence = 0;     // 序列号
    private int $lastTimestamp = -1; // 上次生成ID的时间戳

    /**
     * 构造函数,初始化ID生成器
     * @param int $datacenterId 数据中心ID(0-31)
     * @param int $machineId 机器ID(0-31)
     * @throws Exception 如果ID超出范围
     */
    public function __construct(int $datacenterId, int $machineId)
    {
        // 验证数据中心ID范围
        if ($datacenterId < 0 || $datacenterId > self::MAX_DATA_CENTER_ID) {
            throw new Exception("数据中心ID超出范围");
        }
        // 验证机器ID范围
        if ($machineId < 0 || $machineId > self::MAX_MACHINE_ID) {
            throw new Exception("机器ID超出范围");
        }
        $this->datacenterId = $datacenterId;
        $this->machineId = $machineId;
    }

    /**
     * 生成唯一ID
     * @return int 64位唯一ID
     * @throws Exception 如果时钟发生回拨
     */
    public function nextId(): int
    {
        $timestamp = $this->currentTimeMillis();

        // 检测时钟回拨
        if ($timestamp < $this->lastTimestamp) {
            throw new Exception("错误:系统时钟发生回拨");
        }

        // 同一毫秒内处理序列号递增
        if ($this->lastTimestamp === $timestamp) {
            $this->sequence = ($this->sequence + 1) & ((1 << self::SEQUENCE_BITS) - 1);
            // 序列号溢出,等待下一毫秒
            if ($this->sequence === 0) {
                $timestamp = $this->waitNextMillis($timestamp);
            }
        } else {
            // 新的一毫秒,重置序列号
            $this->sequence = 0;
        }

        // 更新上次时间戳
        $this->lastTimestamp = $timestamp;

        // 组合ID:(时间戳 << 22) | (数据中心ID << 17) | (机器ID << 12) | 序列号
        return (($timestamp - $this->epoch) << self::TIMESTAMP_LEFT_SHIFT) |
               ($this->datacenterId << self::SEQUENCE_LEFT_SHIFT) |
               ($this->machineId << self::SEQUENCE_BITS) |
               $this->sequence;
    }

    /**
     * 等待下一毫秒
     * @param int $lastTimestamp 上次时间戳
     * @return int 下一毫秒时间戳
     */
    private function waitNextMillis(int $lastTimestamp): int
    {
        $timestamp = $this->currentTimeMillis();
        while ($timestamp <= $lastTimestamp) {
            $timestamp = $this->currentTimeMillis();
        }
        return $timestamp;
    }

    /**
     * 获取当前时间戳(毫秒级)
     * @return int
     */
    private function currentTimeMillis(): int
    {
        return (int)(microtime(true) * 1000);
    }
}

// 使用示例
$datacenterId = 1;    // 数据中心ID(0-31)
$machineId = 1;       // 机器ID(0-31)
$snowflake = new Snowflake($datacenterId, $machineId);

for ($i = 0; $i < 10; $i++) {
    $userId = $snowflake->nextId();
    echo "生成的用户ID: {$userId}<br/>";
}

Vercel

php 复制代码
<?php

/**
 * 雪花算法(Snowflake)PHP实现
 * 
 * 雪花算法是由Twitter开发的分布式唯一ID生成算法,结构如下:
 * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
 * 
 * 第1位:符号位,始终为0
 * 第2-42位:41位时间戳(毫秒级),可以使用69年
 * 第43-43位:1位数据中心ID
 * 第44-48位:5位机器ID
 * 第49-53位:5位数据中心内机器ID
 * 第54-64位:12位序列号,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒产生4096个ID序号
 */
class Snowflake {
    /**
     * 开始时间戳(2020-01-01)
     * 这是一个自定义的起始时间,用于计算相对时间戳
     */
    const START_TIMESTAMP = 1577808000000; // 2020-01-01 00:00:00 GMT

    /**
     * 各部分占用的位数
     */
    const SEQUENCE_BITS = 12;       // 序列号占用的位数
    const MACHINE_ID_BITS = 5;      // 机器ID占用的位数
    const DATACENTER_ID_BITS = 5;   // 数据中心ID占用的位数

    /**
     * 各部分的最大值
     */
    const MAX_SEQUENCE = -1 ^ (-1 << self::SEQUENCE_BITS);           // 序列号最大值 4095
    const MAX_MACHINE_ID = -1 ^ (-1 << self::MACHINE_ID_BITS);       // 机器ID最大值 31
    const MAX_DATACENTER_ID = -1 ^ (-1 << self::DATACENTER_ID_BITS); // 数据中心ID最大值 31

    /**
     * 各部分向左的位移
     */
    const MACHINE_ID_SHIFT = self::SEQUENCE_BITS;                                     // 机器ID向左移12位
    const DATACENTER_ID_SHIFT = self::SEQUENCE_BITS + self::MACHINE_ID_BITS;          // 数据中心ID向左移17位
    const TIMESTAMP_SHIFT = self::SEQUENCE_BITS + self::MACHINE_ID_BITS + self::DATACENTER_ID_BITS; // 时间戳向左移22位

    /**
     * @var int 数据中心ID
     */
    private $datacenterId;

    /**
     * @var int 机器ID
     */
    private $machineId;

    /**
     * @var int 毫秒内序列号
     */
    private $sequence = 0;

    /**
     * @var int 上次生成ID的时间戳
     */
    private $lastTimestamp = -1;

    /**
     * 构造函数
     *
     * @param int $datacenterId 数据中心ID (0~31)
     * @param int $machineId 机器ID (0~31)
     * @throws Exception 当数据中心ID或机器ID超出范围时抛出异常
     */
    public function __construct($datacenterId = 0, $machineId = 0) {
        // 检查数据中心ID和机器ID是否在有效范围内
        if ($datacenterId > self::MAX_DATACENTER_ID || $datacenterId < 0) {
            throw new Exception("数据中心ID超出范围: 应为0~" . self::MAX_DATACENTER_ID);
        }
        
        if ($machineId > self::MAX_MACHINE_ID || $machineId < 0) {
            throw new Exception("机器ID超出范围: 应为0~" . self::MAX_MACHINE_ID);
        }
        
        $this->datacenterId = $datacenterId;
        $this->machineId = $machineId;
    }

    /**
     * 获取下一个ID
     *
     * @return string 生成的ID(返回字符串是因为PHP的整数范围可能不足以存储64位ID)
     * @throws Exception 当时钟回拨时抛出异常
     */
    public function nextId() {
        // 获取当前时间戳(毫秒)
        $timestamp = $this->getCurrentTimestamp();
        
        // 检查时钟回拨
        if ($timestamp < $this->lastTimestamp) {
            throw new Exception("时钟回拨,拒绝生成ID,上次时间: " . 
                                $this->lastTimestamp . ", 当前时间: " . $timestamp);
        }
        
        // 如果是同一毫秒内,则增加序列号
        if ($timestamp == $this->lastTimestamp) {
            // 序列号递增
            $this->sequence = ($this->sequence + 1) & self::MAX_SEQUENCE;
            // 如果序列号溢出,则等待下一毫秒
            if ($this->sequence == 0) {
                $timestamp = $this->waitNextMillis($this->lastTimestamp);
            }
        } else {
            // 不同毫秒内,序列号重置为0
            $this->sequence = 0;
        }
        
        // 更新上次生成ID的时间戳
        $this->lastTimestamp = $timestamp;
        
        // 计算相对时间戳(相对于开始时间)
        $timestampDiff = $timestamp - self::START_TIMESTAMP;
        
        // 组合各部分生成ID
        // 注意:PHP的整数范围可能不足以存储64位ID,所以使用字符串或GMP扩展处理大整数
        $id = (($timestampDiff << self::TIMESTAMP_SHIFT) |
               ($this->datacenterId << self::DATACENTER_ID_SHIFT) |
               ($this->machineId << self::MACHINE_ID_SHIFT) |
               $this->sequence);
               
        return (string)$id;
    }

    /**
     * 获取当前时间戳(毫秒)
     *
     * @return int 当前时间戳(毫秒)
     */
    private function getCurrentTimestamp() {
        // 获取微秒级时间戳并转换为毫秒
        return (int)floor(microtime(true) * 1000);
    }

    /**
     * 等待下一毫秒
     *
     * @param int $lastTimestamp 上次生成ID的时间戳
     * @return int 新的时间戳(毫秒)
     */
    private function waitNextMillis($lastTimestamp) {
        $timestamp = $this->getCurrentTimestamp();
        // 循环等待,直到获得新的时间戳
        while ($timestamp <= $lastTimestamp) {
            $timestamp = $this->getCurrentTimestamp();
        }
        return $timestamp;
    }
}

// 使用示例
try {
    // 创建雪花算法实例,参数为数据中心ID和机器ID
    $snowflake = new Snowflake(1, 1);
    
    // 生成10个ID
    echo "生成的ID示例:\n";
    for ($i = 0; $i < 10; $i++) {
        echo $snowflake->nextId() . "\n";
    }
} catch (Exception $e) {
    echo "错误: " . $e->getMessage();
}
?>

文心一言

php 复制代码
<?php
 
class Snowflake {
    // 定义雪花ID的各部分位数
    private const TIMESTAMP_BITS = 41; // 时间戳位数
    private const NODE_ID_BITS = 10;  // 节点ID位数
    private const SEQUENCE_BITS = 12; // 序列号位数
 
    // 定义起始时间戳(这里以2020-01-01为例)
    private const EPOCH = 1577836800000;
 
    // 定义最大取值范围
    private const MAX_NODE_ID = (1 << self::NODE_ID_BITS) - 1;
    private const MAX_SEQUENCE = (1 << self::SEQUENCE_BITS) - 1;
 
    // 定义偏移量
    private const TIMESTAMP_SHIFT = self::NODE_ID_BITS + self::SEQUENCE_BITS;
    private const NODE_ID_SHIFT = self::SEQUENCE_BITS;
 
    private $nodeId;           // 节点ID
    private $lastTimestamp = -1; // 上次生成ID的时间戳
    private $sequence = 0;     // 序列号
 
    /**
     * 构造函数,用于初始化节点ID
     *
     * @param int $nodeId 节点ID
     * @throws InvalidArgumentException 如果节点ID超出范围
     */
    public function __construct($nodeId) {
        if ($nodeId < 0 || $nodeId > self::MAX_NODE_ID) {
            throw new InvalidArgumentException("Invalid node ID, must be between 0 and " . self::MAX_NODE_ID);
        }
        $this->nodeId = $nodeId;
    }
 
    /**
     * 生成下一个唯一的ID
     *
     * @return int 生成的唯一ID
     * @throws RuntimeException 如果系统时钟回拨
     */
    public function generateId() {
        $currentTimestamp = $this->timestamp();
 
        // 检查时钟回拨
        if ($currentTimestamp < $this->lastTimestamp) {
            throw new RuntimeException("Clock moved backwards");
        }
 
        // 如果当前时间戳与上次相同,则递增序列号
        if ($currentTimestamp == $this->lastTimestamp) {
            $this->sequence = ($this->sequence + 1) & self::MAX_SEQUENCE;
 
            // 如果序列号溢出,则等待下一毫秒
            if ($this->sequence == 0) {
                $currentTimestamp = $this->untilNextMillis($this->lastTimestamp);
            }
        } else {
            // 如果时间戳不同,则重置序列号
            $this->sequence = 0;
        }
 
        // 更新上次生成ID的时间戳
        $this->lastTimestamp = $currentTimestamp;
 
        // 组合时间戳、节点ID和序列号生成唯一的ID
        return (($currentTimestamp - self::EPOCH) << self::TIMESTAMP_SHIFT) |
               ($this->nodeId << self::NODE_ID_SHIFT) |
               $this->sequence;
    }
 
    /**
     * 获取当前时间戳(毫秒)
     *
     * @return int 当前时间戳
     */
    private function timestamp() {
        return round(microtime(true) * 1000);
    }
 
    /**
     * 等待下一毫秒
     *
     * @param int $lastTimestamp 上次生成ID的时间戳
     * @return int 下一毫秒的时间戳
     */
    private function untilNextMillis($lastTimestamp) {
        $currentTimestamp = $this->timestamp();
        while ($currentTimestamp <= $lastTimestamp) {
            $currentTimestamp = $this->timestamp();
        }
        return $currentTimestamp;
    }
}
 
// 示例使用
$nodeId = 1; // 设置节点ID
$snowflake = new Snowflake($nodeId);
 
// 生成10个唯一ID
for ($i = 0; $i < 10; $i++) {
    $id = $snowflake->generateId();
    echo "Generated ID: $id\n";
}

讯飞星火

讯飞星火在生成代码的过程中居然出现了BUG, 代码在生成过程中, 开头生成的代码莫名消失, 最后生成的代码如下

php 复制代码
 self::MAX_DATA_CENTER_ID || $dataCenterId < 0) {
            throw new Exception("Data Center ID can't be greater than " . self::MAX_DATA_CENTER_ID . " or less than 0");
        }
        if ($machineId > self::MAX_MACHINE_ID || $machineId < 0) {
            throw new Exception("Machine ID can't be greater than " . self::MAX_MACHINE_ID . " or less than 0");
        }
        $this->dataCenterId = $dataCenterId;
        $this->machineId = $machineId;
    }

    public function nextId() {
        $timestamp = $this->timeGen();

        if ($timestamp < $this->lastTimestamp) {
            throw new Exception("Clock moved backwards. Refusing to generate id for " . ($this->lastTimestamp - $timestamp) . " milliseconds");
        }

        if ($this->lastTimestamp == $timestamp) {
            $this->sequence = ($this->sequence + 1) &amp; self::MAX_SEQUENCE;
            if ($this->sequence == 0) {
                $timestamp = $this->tilNextMillis($this->lastTimestamp);
            }
        } else {
            $this->sequence = 0;
        }

        $this->lastTimestamp = $timestamp;

        return (($timestamp - self::EPOCH) << self::TIMESTAMP_SHIFT) |
               ($this->dataCenterId << self::DATA_CENTER_ID_SHIFT) |
               ($this->machineId << self::MACHINE_ID_SHIFT) |
               $this->sequence;
    }

    protected function tilNextMillis($lastTimestamp) {
        $timestamp = $this->timeGen();
        while ($timestamp <= $lastTimestamp) {
            $timestamp = $this->timeGen();
        }
        return $timestamp;
    }

    protected function timeGen() {
        return round(microtime(true) * 1000); // 获取当前时间的毫秒级时间戳
    }
}

// 使用示例
try {
    $snowflake = new Snowflake(1, 1); // 数据中心ID和机器ID都设置为1
    echo $snowflake->nextId(); // 生成一个唯一的ID
} catch (Exception $e) {
    echo 'Error: ' . $e->getMessage();
}
?>
相关推荐
桦037 分钟前
每天一道算法题【蓝桥杯】【山脉数组的峰顶索引】
c++·算法·leetcode·蓝桥杯
2301_8008951037 分钟前
蓝桥杯好数
算法
yngsqq2 小时前
贪心算法和遗传算法优劣对比——c#
算法·贪心算法·c#
Hacker_Nightrain2 小时前
网络安全防护总体架构 网络安全防护工作机制
web安全·架构·php
onlyzzr2 小时前
Leetcode Hot100 第58题 23.合并K个升序链表
java·算法·leetcode
修己xj2 小时前
算法系列之回溯算法求解数独及所有可能解
算法
剑海风云2 小时前
73. 矩阵置零
java·数据结构·算法·矩阵
冠位观测者3 小时前
【Leetcode 每日一题】3306. 元音辅音字符串计数 II
数据结构·算法·leetcode
自由的晚风3 小时前
脑电波控制设备:基于典型相关分析(CCA)的脑机接口频率精准解码方法
人工智能·经验分享·笔记·算法·matlab·脑机接口·ssvep