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 24 Javascript
javascript setinterval 的正确语法如何书写
Jun 17 Javascript
jQuery unbind()方法实例详解
Jan 19 Javascript
jQuery基于ID调用指定iframe页面内的方法
Jul 06 Javascript
BootStrap整体框架之基础布局组件
Dec 15 Javascript
基于Swiper实现移动端页面图片轮播效果
Dec 28 Javascript
基于react后端渲染模板引擎noox发布使用
Jan 11 Javascript
微信小程序实现YDUI的ScrollTab组件
Feb 02 Javascript
JS实现倒计时图文效果
Nov 17 Javascript
微信小程序与后台PHP交互的方法实例分析
Dec 10 Javascript
小程序获取当前位置加搜索附近热门小区及商区的方法
Apr 08 Javascript
javascript实现动态时钟的启动和停止
Jul 29 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
dedecms防止FCK乱格式化你的代码的修改方法
2007/03/17 PHP
php实现登录tplink WR882N获取IP和重启的方法
2016/07/20 PHP
Mac系统完美安装PHP7详细教程
2017/06/06 PHP
php+jQuery ajax实现的实时刷新显示数据功能示例
2019/09/12 PHP
javascript YUI 读码日记之 YAHOO.util.Dom - Part.4
2008/03/22 Javascript
jquery 可排列的表实现代码
2009/11/13 Javascript
JavaScript类型转换方法及需要注意的问题小结(挺全面)
2010/11/11 Javascript
prettify 代码高亮着色器google出品
2010/12/28 Javascript
jQuery页面滚动浮动层智能定位实例代码
2011/08/23 Javascript
js 判断计算字符串长度/判断空的简单方法
2013/08/05 Javascript
jquery live()调用不存在的解决方法
2014/02/26 Javascript
javascript使用数组的push方法完成快速排序
2014/09/15 Javascript
JavaScript正则替换HTML标签功能示例
2017/03/02 Javascript
微信小程序 获取session_key和openid的实例
2017/08/17 Javascript
基于滚动条位置判断的简单实例
2017/12/14 Javascript
详解javascript中的babel到底是什么
2018/06/21 Javascript
解决vue 单文件组件中样式加载问题
2019/04/24 Javascript
Vue 实现前端权限控制的示例代码
2019/07/09 Javascript
python中字典(Dictionary)用法实例详解
2015/05/30 Python
python如何实现excel数据添加到mongodb
2015/07/30 Python
Python实现查找匹配项作处理后再替换回去的方法
2017/06/10 Python
python enumerate函数的使用方法总结
2017/11/15 Python
Python实现基于TCP UDP协议的IPv4 IPv6模式客户端和服务端功能示例
2018/03/22 Python
Python常见内置高效率函数用法示例
2018/07/31 Python
python实现年会抽奖程序
2019/01/22 Python
python判断单向链表是否包括环,若包含则计算环入口的节点实例分析
2019/10/23 Python
python下载的库包存放路径
2020/07/27 Python
Python爬虫实现selenium处理iframe作用域问题
2021/01/27 Python
本科生个人求职自荐信
2013/09/26 职场文书
营业员个人总结的自我评价
2013/10/25 职场文书
音乐专业应届生教师求职信
2013/11/04 职场文书
财务管理专业毕业生求职信
2014/06/02 职场文书
安全生产先进个人事迹材料
2014/12/30 职场文书
教师节寄语2015
2015/03/23 职场文书
施工现场安全管理制度
2015/08/05 职场文书
Java使用JMeter进行高并发测试
2021/11/23 Java/Android