Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
N
note
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
黄夏豪
note
Commits
430fb793
提交
430fb793
authored
5月 28, 2020
作者:
黄夏豪
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
文件名错误修改
上级
c0fbc2b8
隐藏空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
103 行增加
和
0 行删除
+103
-0
什么是雪花算法.md
黄夏豪/什么是雪花算法.md
+103
-0
没有找到文件。
黄夏豪/什么是雪花算法.md
0 → 100644
浏览文件 @
430fb793
## 什么是雪花算法
雪花算法时由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
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论