提交 b037ecca authored 作者: xuyang's avatar xuyang
## 什么是雪花算法
雪花算法时由Twitter公司提出的一种生成唯一ID的生成算法,能够生成一个具有唯一性64位的整数ID。
## 为什么使用雪花算法
在分布式系统中,多台服务器对同一个实体进行操作时需要赋予一个唯一ID。例如:同一个系统中每个用户具有唯一的ID主键。
## 详解
在雪花算法中,讲一个64的整数分为4块,分别存放符号、时间戳、机器号、序列号
1. 符号位 占1Bit 由于整数的 第一位为符号位切 分布式ID默认以正数存在所以 第一位 默认为 1
2. 时间戳 一般占41bit 也就是2的41次方 大概可以用69年。假如需要更长的时间可以缩减机器号或者序列号的位置 讲多出来的空间分给 时间戳
3. 机器号 一般占据10bit 也就是最多能够支持 2的10次方 共 1024台机器同时使用
4. 序列号 一般占12bit 也就是2的12次方 也就是说 每毫秒做多生成 4096个序列号,每秒能够支持4_096_000QPS
```JAVA
public class SnowFake {
//机器ID位数
private static final long workIdLength = 10l;
//机器ID最大值
private static final long maxWorkId = 1l<<workIdLength;
//每秒产生的序列号位数
private static final long sequenceLength = 12l;
//每秒产生的序列号最大值
private static final long maxSequence = 1l<<sequenceLength;
//时间戳位数
private static final long timestampLength = 63-(workIdLength+sequenceLength);
//默认给了一个机器码
private static final long workId = 116l;
//用于记录上一毫秒的时间戳
private static long lastTimestamp = 0l;
//用于记录上一个序列号
private static long sequence = 0l;
//机器号左偏移量
private static final long workIdOffset = sequenceLength;
//时间戳左编译量
private static final long timestampOffset = sequenceLength + workIdLength;
/***
* 描述:获取雪花算法ID
* @Return : long
* @Author : HuangXiahao
* @Date : 2020/5/22 15:31
*/
public static long nextId(){
//获取当前时间戳
long l = System.currentTimeMillis();
if (lastTimestamp==l){
//如果当前时间与上一次获取的时间相同则获取当前时间对应的序列号
//如果当前时间能获取序列号已经到达最大数量则顺延到下一毫秒再获取序列号
if (sequence==maxSequence){
//进入下一毫秒并将序列号重置
nextTime(l);
}else {
sequence ++;
}
}else {
//重置时间戳记录和序列号
lastTimestamp = l;
sequence = 0;
}
//将数据移动到对应的位置上
return l<<(timestampOffset)|workId<<(sequenceLength)|sequence;
}
/***
* 描述:进入下一毫秒并重置序列号和时间记录
* @Return : void
* @Author : HuangXiahao
* @Date : 2020/5/22 15:39
*/
public static void nextTime(long previouTimestamp){
long currentTime = System.currentTimeMillis();
while (currentTime<=previouTimestamp){
sequence = 0;
lastTimestamp = currentTime;
return;
}
}
public static void main(String[] args) {
long last = 0l;
for (int i = 0; i <999999999 ; i++) {
long l = nextId();
if (last!=l){
last = l;
System.out.println(l);
}else {
System.out.println("重复了");
}
}
System.out.println("跑完了");
}
}
```
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论