SnowFlake.php

本文介绍了PHP中实现雪花ID生成器的SnowFlake类,该类用于生成具有时间戳、数据中心和机器标识的唯一ID。通过设置不同的数据中心和机器标识,可以在分布式环境中保证ID的全局唯一性。示例代码展示了如何使用SnowFlake类生成ID,并将其与日期结合形成一个字符串。
摘要由CSDN通过智能技术生成

* SnowFlake.php

<?php


namespace CarV2\Utils;


class SnowFlake
{
    const START_STAMP = 1640966400000;  // "2022-01-01"
    const SEQUENCE_BIT = 12; // 序列号占用的位数
    const MACHINE_BIT = 5;  // 机器标识占用的位数
    const DATACENTER_BIT = 5;  // 数据中心占用的位数

    const MAX_DATACENTER_NUM = -1 ^ (-1 << self::DATACENTER_BIT); // 0x8000000000000001
    const MAX_MACHINE_NUM = -1 ^ (-1 << self::MACHINE_BIT);
    const MAX_SEQUENCE = -1 ^ (-1 << self::SEQUENCE_BIT);

    const MACHINE_LEFT = self::SEQUENCE_BIT;
    const DATACENTER_LEFT = self::SEQUENCE_BIT + self::MACHINE_BIT;
    const TIMESTAMP_LEFT = self::DATACENTER_LEFT + self::DATACENTER_BIT;

    /** @var int */
    private $datacenterId;
    /** @var int */
    private $machineId;
    /** @var int */
    private $sequence = 0;
    /** @var int */
    private $lastStamp = -1;

    public function __construct(int $dcId, int $mId) {
        if ($dcId < 0 || self::MAX_DATACENTER_NUM < $dcId) {
            throw new \InvalidArgumentException(
                "datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");
        }
        if ($mId < 0 || self::MAX_MACHINE_NUM < $mId) {
            throw new \InvalidArgumentException(
                "machineId can't be greater than MAX_MACHINE_NUM or less than 0");
        }
        $this->datacenterId = $dcId;
        $this->machineId = $mId;
    }

    public function nextId() {
        $currStamp = self::timeGen();
        if ($currStamp < $this->lastStamp) {
            throw new RuntimeException("Clock moved backwards.  Refusing to generate id");
        }
        if ($currStamp - $this->lastStamp == 0) {
            $this->sequence = ($this->sequence + 1) & self::MAX_SEQUENCE;
            if ($this->sequence == 0) {
                $currStamp = $this->getNextMill();
            }
        } else {
            $this->sequence = 0;
        }
        $this->lastStamp = $currStamp;
        return ($currStamp - self::START_STAMP) << self::TIMESTAMP_LEFT //时间戳部分
            | $this->datacenterId << self::DATACENTER_LEFT       //数据中心部分
            | $this->machineId << self::MACHINE_LEFT             //机器标识部分
            | $this->sequence;                             //序列号部分
    }

    private function getNextMill() {
        $mill = self::timeGen();
        while ($mill - $this->lastStamp <= 0) {
            $mill = self::timeGen();
        }
        return $mill;
    }

    private static function timeGen() {
        list($ms, $sec) = explode(' ', microtime());
        return round((floatval($ms) + floatval($sec)) * 1000);
    }
}

Usage:

    public function genAppNo() : string {
        $datacenterId = rand(1, 4);
        $machineId = rand(1,31);
        $sf = new SnowFlake($datacenterId, $machineId);
        $nextId = strval($sf->nextId());
        return date("ymd").substr($nextId, 6);
    }

string(17) "22031195022706688"

雪花算法(snowflake)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fareast_mzh

打赏个金币

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值