当前位置: 首页 > 工具软件 > php_snowflake > 使用案例 >

php简洁版雪花算法Snowflake

强德厚
2023-12-01

原理介绍:

Snowflake的核心思想是将64bit的二进制数字分成若干部分,每一部分都存储有特定含义的数据,比如说时间戳、机房ID、机器ID、序列号等等,最终生成全局唯一的有序ID。它的标准算法是这样的:

0       0000000000000000000000000000000000000000  0000000000   000000000000
符号位  41位时间戳,大约够69年                    10位(机房+机器ID)  12位序列号   

具体位数怎么分配,其实可以根据自己的情况来,比如如果只有两个机器,那么用10位显然是浪费的,根据自己情况分配即可

相关知识:

二进制转十进制:

比如 11010[2进制] = 1X2^4+1X2^3+0X2^2+1X2^1+0X2^0
=26[10进制],二进制数转换成十进制数的方法是按权展开就是这样做的
注:2^4表示2的4次方,任何非0数字的0次方都等于1

十进制转二进制:

789=1100010101
789/2=394 余1 第10位
394/2=197 余0 第9位
197/2=98 余1 第8位
98/2=49 余0 第7位
49/2=24 余1 第6位
24/2=12 余0 第5位
12/2=6 余0 第4位
6/2=3 余0 第3位
3/2=1 余1 第2位
1/2=0 余1 第1位

最后把余数从下往上连起来即为: 1100010101

PHP实现

<?php
/**
 *  分布式 id 生成类     组成: <毫秒级时间戳+机房id+机器id+序列号>
 *  默认情况下41bit的时间戳可以支持该算法使用69年,5bit的机房id可以支持31台机器,5bit的工作机器id可以支持31台机器,序列号支持1毫秒产生4095个自增序列id
 */
class IdCreate
{
    const EPOCH = 1640856551866;    //开始时间,固定一个小于当前时间的毫秒数,这样后续的时间戳毫秒基于此开始时间才能达到69年;
    const max12bit = 4095;

    static $dataCenterId = null;      // 机房id
    static $machineId = null;      // 机器id

    public static function createOnlyId($dataCenterId = 0,$machineId = 0)
    {
        self::$machineId = $machineId;
        self::$dataCenterId = $dataCenterId;
        // 时间戳 41字节
        $time = floor(microtime(true) * 1000);
        // 当前时间 与 开始时间 差值,这样就可以有69年的时间
        $time -= self::EPOCH;
        // 二进制的 毫秒级时间戳
        $timeStr = str_pad(decbin($time), 41, "0", STR_PAD_LEFT);
        // 机房id  5 字节
        $dataCenterId = str_pad(decbin(self::$dataCenterId), 5, "0", STR_PAD_LEFT);
        // 机器id  5 字节
        $machineId = str_pad(decbin(self::$machineId), 5, "0", STR_PAD_LEFT);

        // 序列数 12字节
        $random = str_pad(decbin(mt_rand(0, self::max12bit)), 12, "0", STR_PAD_LEFT);
        //正常应该搞自增id,这里为了演示,所以用了随机数,使用redis的自增id比较好:
        //REDIS::incr($time.self::$dataCenterId.self::$machineId);
        // 拼接
        $base = $timeStr.$dataCenterId.$machineId.$random;
        // 转化为 十进制 返回
        return bindec($base);
    }
}
    $dataCenterId = 2;
    $machineId = 1;
    $cast_id = IdCreate::createOnlyId($dataCenterId,$machineId);
    echo $cast_id;

生成唯一值

13648311620966
 类似资料: