PHP实现雪花算法生成唯一ID

雪花算法是Twitter开源的分布式ID生成算法,可以产生64位的ID。其中第一位是固定的正数标识,41位用于存储时间戳,剩下的为机器ID和序列号。通过时间戳、机器ID和序列号的组合,确保每个ID都是唯一的。

class Snowflake
{
    private  $datacenterId; // 数据中心ID
    private  $machineId;    // 机器ID
    private  $sequence = 0; // 序列号
    private  $lastTimestamp = -1; // 上一个时间戳

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

    private const MAX_DATA_CENTER_ID = -1 ^ (-1 << self::DATA_CENTER_ID_BITS);
    private const MAX_MACHINE_ID = -1 ^ (-1 << self::MACHINE_ID_BITS);

    private const TIMESTAMP_LEFT_SHIFT = self::SEQUENCE_BITS + self::MACHINE_ID_BITS + self::DATA_CENTER_ID_BITS;
    private const SEQUENCE_LEFT_SHIFT = self::MACHINE_ID_BITS + self::DATA_CENTER_ID_BITS;

    private $epoch; // 起始时间戳

    public function __construct( $datacenterId, $machineId)
    {
        if ($datacenterId < 0 || $datacenterId > self::MAX_DATA_CENTER_ID) {
            throw new Exception("数据中心ID超出范围");
        }

        if ($machineId < 0 || $machineId > self::MAX_MACHINE_ID) {
            throw new Exception("机器ID超出范围");
        }

        $this->datacenterId = $datacenterId;
        $this->machineId = $machineId;
        $this->epoch = 1609430400000; // 自定义起始时间(例如2021年1月1日)
    }

    public function nextId()
    {
        $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;

        return (($timestamp - $this->epoch) << self::TIMESTAMP_LEFT_SHIFT) |
            ($this->datacenterId << self::SEQUENCE_LEFT_SHIFT) |
            ($this->machineId << self::SEQUENCE_BITS) |
            $this->sequence;
    }

    private function waitNextMillis($lastTimestamp)
    {
        $timestamp = $this->currentTimeMillis();
        while ($timestamp <= $lastTimestamp) {
            $timestamp = $this->currentTimeMillis();
        }
        return $timestamp;
    }

    private function currentTimeMillis()
    {
        return (int)(microtime(true) * 1000);
    }
}
 // 创建雪花算法实例
 $datacenterId = 1; // 数据中心ID
 $machineId = 1;    // 机器ID
 $snowflake = new Snowflake($datacenterId, $machineId);
 // 生成用户ID的示例
 for ($i = 0; $i < 10; $i++) {
     $userId = $snowflake->nextId();
     echo "生成的用户ID: $userId"."<br/>";
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值