实现雪花算法(Snowflake Algorithm)的步骤
确定时间戳占多少位:由于雪花算法的最小时间单位为毫秒,假如要标识的时间跨度为41年,可以确定能用到的时钟位数是41 (2^41-1)/1000/60/60/24/365=41,也就是说64bit的ID中时间戳部分需要占据42位。
确定机器标识占多少位:机器标识需要在集群中唯一,这里对numOfWorkingIds设置为2^10-1=1023,即可分配1024台服务器,机器标识部分占用10位。
确定序列号占多少位:序列号可以设置最大值,这里设置序列号最大值为4095 ,即2^12-1, 则此部分占 12 位,最后剩下 2 个 bit 。
PHP 代码
const tokenBits = {
timestamp: 41,
workerId: 10,
sequence: 12
}
class Snowflake {
public static function generate() {
// get current timestamp
$timestamp = floor(microtime(true) * 1000);
// the id starts with the timestamp
$baseId = bcadd(bcmul($timestamp, '1' . str_repeat('0', tokenBits['timestamp'])), 0);
// add a random worker id
$baseId = bcadd(bcmul(str_pad(mt_rand(1, 1023), tokenBits['workerId'], '0', STR_PAD_LEFT), bcpow('2', tokenBits['timestamp'])), $baseId);
// add a sequence counter we start from 0
$baseId = bcadd(bcmul(str_pad($sequence, tokenBits['sequence'], '0', STR_PAD_LEFT), bcpow('2', tokenBits['timestamp'] + tokenBits['workerId'])), $baseId);
return $baseId;
}
}