Js Snowflake(雪花算法)生成随机ID的实现方法


Posted in Javascript onAugust 26, 2020

1、snowflake-id插件 

import SnowflakeId from "snowflake-id";

const guid = num => {
 const id= new SnowflakeId();
 return id.generate();
};

2、原生使用 

var Snowflake = /** @class */ (function() {
	function Snowflake(_workerId, _dataCenterId, _sequence) {
		this.twepoch = 1288834974657n;
		//this.twepoch = 0n;
		this.workerIdBits = 5n;
		this.dataCenterIdBits = 5n;
		this.maxWrokerId = -1n ^ (-1n << this.workerIdBits); // 值为:31
		this.maxDataCenterId = -1n ^ (-1n << this.dataCenterIdBits); // 值为:31
		this.sequenceBits = 12n;
		this.workerIdShift = this.sequenceBits; // 值为:12
		this.dataCenterIdShift = this.sequenceBits + this.workerIdBits; // 值为:17
		this.timestampLeftShift = this.sequenceBits + this.workerIdBits + this.dataCenterIdBits; // 值为:22
		this.sequenceMask = -1n ^ (-1n << this.sequenceBits); // 值为:4095
		this.lastTimestamp = -1n;
		//设置默认值,从环境变量取
		this.workerId = 1n;
		this.dataCenterId = 1n;
		this.sequence = 0n;
		if(this.workerId > this.maxWrokerId || this.workerId < 0) {
			thrownew Error('_workerId must max than 0 and small than maxWrokerId-[' + this.maxWrokerId + ']');
		}
		if(this.dataCenterId > this.maxDataCenterId || this.dataCenterId < 0) {
			thrownew Error('_dataCenterId must max than 0 and small than maxDataCenterId-[' + this.maxDataCenterId + ']');
		}

		this.workerId = BigInt(_workerId);
		this.dataCenterId = BigInt(_dataCenterId);
		this.sequence = BigInt(_sequence);
	}
	Snowflake.prototype.tilNextMillis = function(lastTimestamp) {
		var timestamp = this.timeGen();
		while(timestamp <= lastTimestamp) {
			timestamp = this.timeGen();
		}
		return BigInt(timestamp);
	};
	Snowflake.prototype.timeGen = function() {
		return BigInt(Date.now());
	};
	Snowflake.prototype.nextId = function() {
		var timestamp = this.timeGen();
		if(timestamp < this.lastTimestamp) {
			thrownew Error('Clock moved backwards. Refusing to generate id for ' +
				(this.lastTimestamp - timestamp));
		}
		if(this.lastTimestamp === timestamp) {
			this.sequence = (this.sequence + 1n) & this.sequenceMask;
			if(this.sequence === 0n) {
				timestamp = this.tilNextMillis(this.lastTimestamp);
			}
		} else {
			this.sequence = 0n;
		}
		this.lastTimestamp = timestamp;
		return((timestamp - this.twepoch) << this.timestampLeftShift) |
			(this.dataCenterId << this.dataCenterIdShift) |
			(this.workerId << this.workerIdShift) |
			this.sequence;
	};
	return Snowflake;
}());

console.log(new Snowflake(1n, 1n, 0n).nextId());
//1141531990672150528n

控制台输出1141531990672150528n为bigint格式, .toString()转为字符串格式即可

3、ES6使用

import bigInt from "big-integer";

const guid = () => {
 const Snowflake = /** @class */ (function() {
  function Snowflake(_workerId, _dataCenterId, _sequence) {
   // this.twepoch = 1288834974657;
   this.twepoch = 0;
   this.workerIdBits = 5;
   this.dataCenterIdBits = 5;
   this.maxWrokerId = -1 ^ (-1 << this.workerIdBits); // 值为:31
   this.maxDataCenterId = -1 ^ (-1 << this.dataCenterIdBits); // 值为:31
   this.sequenceBits = 12;
   this.workerIdShift = this.sequenceBits; // 值为:12
   this.dataCenterIdShift = this.sequenceBits + this.workerIdBits; // 值为:17
   this.timestampLeftShift = this.sequenceBits + this.workerIdBits + this.dataCenterIdBits; // 值为:22
   this.sequenceMask = -1 ^ (-1 << this.sequenceBits); // 值为:4095
   this.lastTimestamp = -1;
   //设置默认值,从环境变量取
   this.workerId = 1;
   this.dataCenterId = 1;
   this.sequence = 0;
   if (this.workerId > this.maxWrokerId || this.workerId < 0) {
    throw new Error(
     'config.worker_id must max than 0 and small than maxWrokerId-[' + this.maxWrokerId + ']'
    );
   }
   if (this.dataCenterId > this.maxDataCenterId || this.dataCenterId < 0) {
    throw new Error(
     'config.data_center_id must max than 0 and small than maxDataCenterId-[' +
      this.maxDataCenterId +
      ']'
    );
   }
   this.workerId = _workerId;
   this.dataCenterId = _dataCenterId;
   this.sequence = _sequence;
  }
  Snowflake.prototype.tilNextMillis = function(lastTimestamp) {
   var timestamp = this.timeGen();
   while (timestamp <= lastTimestamp) {
    timestamp = this.timeGen();
   }
   return timestamp;
  };
  Snowflake.prototype.timeGen = function() {
   //new Date().getTime() === Date.now()
   return Date.now();
  };
  Snowflake.prototype.nextId = function() {
   var timestamp = this.timeGen();
   if (timestamp < this.lastTimestamp) {
    throw new Error(
     'Clock moved backwards. Refusing to generate id for ' + (this.lastTimestamp - timestamp)
    );
   }
   if (this.lastTimestamp === timestamp) {
    this.sequence = (this.sequence + 1) & this.sequenceMask;
    if (this.sequence === 0) {
     timestamp = this.tilNextMillis(this.lastTimestamp);
    }
   } else {
    this.sequence = 0;
   }
   this.lastTimestamp = timestamp;
   var shiftNum =
    (this.dataCenterId << this.dataCenterIdShift) |
    (this.workerId << this.workerIdShift) |
    this.sequence; // dataCenterId:1,workerId:1,sequence:0 shiftNum:135168
   var nfirst = new bigInt(String(timestamp - this.twepoch), 10);
   nfirst = nfirst.shiftLeft(this.timestampLeftShift);
   var nnextId = nfirst.or(new bigInt(String(shiftNum), 10)).toString(10);
   return nnextId;
  };
  return Snowflake;
 })();

 return new Snowflake(1, 1, 0).nextId();
};

guid()即可调用

4、多次重复调用出现一样id的bug

console.log(guid(), new Date().getTime());
  console.log(guid(), new Date().getTime());
  console.log(guid(), new Date().getTime());
  console.log(guid(), new Date().getTime());
  console.log(guid(), new Date().getTime());
  console.log(guid(), new Date().getTime());
  console.log(guid(), new Date().getTime());
  console.log(guid(), new Date().getTime());
  console.log(guid(), new Date().getTime());
  console.log(guid(), new Date().getTime());
  console.log(guid(), new Date().getTime());
  console.log(guid(), new Date().getTime());

Js Snowflake(雪花算法)生成随机ID的实现方法

修改如下

import SnowflakeId from "snowflake-id";

const guid = num => {
 const snowflake = new SnowflakeId();
 let arr = [];
 for (let i = 0; i < num; i++) {
  arr.push(snowflake.generate());
 }
 return num ? arr : snowflake.generate();
};

单个调用 guid()

n个调用 guid(n)

文档

到此这篇关于Js Snowflake(雪花算法)生成随机ID的实现方法的文章就介绍到这了,更多相关Js 雪花算法生成随机ID内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
JS 字符串连接[性能比较]
May 10 Javascript
js获取当前select 元素值的代码
Apr 19 Javascript
js 文本滚动效果的实例代码
Aug 17 Javascript
在js文件中写el表达式取不到值的原因及解决方法
Dec 23 Javascript
js+HTML5基于过滤器从摄像头中捕获视频的方法
Jun 16 Javascript
BootStrap3学习笔记(一)之网格系统
May 20 Javascript
jquery 判断是否支持Placeholder属性的方法
Feb 07 Javascript
浅谈React前后端同构防止重复渲染
Jan 05 Javascript
vue2.0 路由不显示router-view的解决方法
Mar 06 Javascript
如何使用 vue-cli 创建模板项目
Nov 19 Vue.js
jQuery实现容器间的元素拖拽功能
Dec 01 jQuery
为什么node.js不适合大型项目
Apr 28 Javascript
uin-app+mockjs实现本地数据模拟
Aug 26 #Javascript
一篇文章带你搞懂Vue虚拟Dom与diff算法
Aug 25 #Javascript
微信小程序换肤功能实现代码(思路详解)
Aug 25 #Javascript
prettier自动格式化去换行的实现代码
Aug 25 #Javascript
Vue中 axios delete请求参数操作
Aug 25 #Javascript
React实现轮播效果
Aug 25 #Javascript
React实现全选功能
Aug 25 #Javascript
You might like
php后台程序与Javascript的两种交互方式
2009/10/25 PHP
基于PHP静态类的原罪详解
2013/05/06 PHP
PHP安装threads多线程扩展基础教程
2015/11/17 PHP
简单概括PHP的字符串中单引号与双引号的区别
2016/05/07 PHP
php 的反射详解及示例代码
2016/08/25 PHP
基于ThinkPHP5.0实现图片上传插件
2017/09/25 PHP
Javascript客户端脚本的设计和应用
2006/08/21 Javascript
学习JavaScript正则表达式
2015/11/13 Javascript
jQuery插件echarts实现的单折线图效果示例【附demo源码下载】
2017/03/04 Javascript
Vue组件中prop属性使用说明实例代码详解
2018/05/31 Javascript
详解KOA2如何手写中间件(装饰器模式)
2018/10/11 Javascript
浅谈React碰到v-if
2018/11/04 Javascript
详解Vue.js在页面加载时执行某个方法
2018/11/20 Javascript
vue-froala-wysiwyg 富文本编辑器功能
2019/09/19 Javascript
vue实现信息管理系统
2020/05/30 Javascript
小程序实现tab标签页
2020/11/16 Javascript
[01:26]神话结束了,却也刚刚开始——DOTA2新英雄玛尔斯驾临战场
2019/03/10 DOTA
python在windows下创建隐藏窗口子进程的方法
2015/06/04 Python
Python中字典(dict)合并的四种方法总结
2017/08/10 Python
python实现随机梯度下降(SGD)
2020/03/24 Python
Python3处理HTTP请求的实例
2018/05/10 Python
关于Python的一些学习总结
2018/05/25 Python
python爬虫 基于requests模块发起ajax的get请求实现解析
2019/08/20 Python
Pytorch之卷积层的使用详解
2019/12/31 Python
Python第三方包PrettyTable安装及用法解析
2020/07/08 Python
CSS3 Pie工具推荐--让IE6-8支持一些优秀的CSS3特性
2014/09/02 HTML / CSS
基于HTML5 的人脸识别活体认证的实现方法
2016/06/22 HTML / CSS
MCAKE蛋糕官方网站:一直都是巴黎的味道
2018/02/06 全球购物
JVM是一个编译程序还是解释程序
2012/09/11 面试题
村优秀党员事迹材料
2014/01/15 职场文书
财务总监岗位职责范本
2015/04/03 职场文书
《当代神农氏》教学反思
2016/02/23 职场文书
创业计划书之干洗店
2019/09/10 职场文书
MySQL连表查询分组去重的实现示例
2021/07/01 MySQL
SQL SERVER存储过程用法详解
2022/02/24 SQL Server
JavaScript实现两个数组的交集
2022/03/25 Javascript