原理介绍:

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

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信