雪花算法是一种分布式唯一ID生成算法,可以保证在分布式环境下,生成的ID是唯一的。以下是一个PHP实现的雪花算法:

class Snowflake {
    const EPOCH = 1479533469598; //起始时间戳,可以设置自己的起始时间
    const SEQUENCE_BITS = 12; //序列号占用的位数
    const WORKER_ID_BITS = 5; //机器标识占用的位数
    const DATACENTER_ID_BITS = 5; //数据中心占用的位数

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

    public function __construct($workerId, $datacenterId) {
        $maxWorkerId = -1 ^ (-1 << self::WORKER_ID_BITS);
        $maxDatacenterId = -1 ^ (-1 << self::DATACENTER_ID_BITS);
        if ($workerId > $maxWorkerId || $workerId < 0) {
            throw new Exception("workerId can't be greater than {$maxWorkerId} or less than 0");
        }
        if ($datacenterId > $maxDatacenterId || $datacenterId < 0) {
            throw new Exception("datacenterId can't be greater than {$maxDatacenterId} or less than 0");
        }
        $this->workerId = $workerId;
        $this->datacenterId = $datacenterId;
    }

    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 ($timestamp == $this->lastTimestamp) {
            $this->sequence = ($this->sequence + 1) & (-1 ^ (-1 << self::SEQUENCE_BITS));
            if ($this->sequence == 0) {
                $timestamp = $this->tilNextMillis($this->lastTimestamp);
            }
        } else {
            $this->sequence = 0;
        }
        $this->lastTimestamp = $timestamp;
        $timestamp = ($timestamp - self::EPOCH) << (self::SEQUENCE_BITS + self::WORKER_ID_BITS + self::DATACENTER_ID_BITS);
        $workerId = $this->workerId << (self::SEQUENCE_BITS + self::DATACENTER_ID_BITS);
        $datacenterId = $this->datacenterId << self::SEQUENCE_BITS;
        return $timestamp | $workerId | $datacenterId | $this->sequence;
    }

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

    private function timeGen() {
        return floor(microtime(true) * 1000);
    }
}

使用示例:

$snowflake = new Snowflake(1, 2); //机器标识为1,数据中心标识为2
echo $snowflake->nextId();

注:该PHP实现未考虑并发安全问题,如果需要高并发下使用,请自行添加相关的并发控制机制。

雪花算法 php

原文地址: https://www.cveoy.top/t/topic/bjm3 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录