导入
帮助我们在分布式系统中生成一个有序且全局唯一的ID,由于自然界中并不存在两片完全一样的雪花,所以这样命名
原理
生成一个64位的Long类型数字id把这64位分成几个部分,每个部分都有自己的生产规则,最后拼接起来即可。
1位标识符——代表正负,由于标识符肯定是正数,所以我们的取值一定是0
41位时间戳精确到毫秒级别,69年(2^41^)
10位工作机器位——我们可以部署到 1024节点上
12位序列号用来记录同毫秒内产生的不同id既可以用——4095个数字
算法实现
public synchronized long nextId() {
// 这儿就是获取当前时间戳,单位是毫秒
long timestamp = System.currentTimeMillis();
//获取当前时间戳如果等于上次时间戳(同一毫秒内),则序号加一,否则序号为0
if (lastTimestamp == timestamp) {
// 这个意思是说一个毫秒内最多只能有4096个数字,无论你传递多少进来,
//这个位运算保证始终就是在4096这个范围内,避免你自己传递个sequence超过了4096这个范围
sequence = (sequence + 1) & sequenceMask;
//当某一毫秒的时间,产生的id数 超过4095,系统会进入等待,直到下一毫秒,系统继续产生ID
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0;
}
// 将上次时间戳刷新
lastTimestamp = timestamp;
// 这儿就是最核心的二进制位运算操作,生成一个64bit的id
// 先将当前时间戳左移22位,后面就有22个0,之后对我们的机器位左移12位,序号位无需左移,用或运算相加
return ((timestamp - twepoch) << timestampLeftShift) |
(datacenterId << datacenterIdShift) |
(workerId << workerIdShift) | sequence;
}