You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.js 9.3 kB

4 years ago
2 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /**
  2. * @description:
  3. * @author: bubao
  4. */
  5. class Genid {
  6. /**
  7. *Creates an instance of Genid.
  8. * @author bubao
  9. * @param {{
  10. * Method: 1, // 雪花计算方法,(1-漂移算法|2-传统算法),默认 1
  11. * BaseTime: 1577836800000, // 基础时间(ms 单位),不能超过当前系统时间
  12. * WorkerId: Number, // 机器码,必须由外部设定,最大值 2^WorkerIdBitLength-1
  13. * WorkerIdBitLength: 6, // 机器码位长,默认值 6,取值范围 [1, 15](要求:序列数位长+机器码位长不超过 22)
  14. * SeqBitLength: 6, // 序列数位长,默认值 6,取值范围 [3, 21](要求:序列数位长+机器码位长不超过 22)
  15. * MaxSeqNumber: 5, // 最大序列数(含),设置范围 [MinSeqNumber, 2^SeqBitLength-1],默认值 0,表示最大序列数取最大值(2^SeqBitLength-1])
  16. * MinSeqNumber: 5, // 最小序列数(含),默认值 5,取值范围 [5, MaxSeqNumber],每毫秒的前 5 个序列数对应编号 0-4 是保留位,其中 1-4 是时间回拨相应预留位,0 是手工新值预留位
  17. * TopOverCostCount: 2000// 最大漂移次数(含),默认 2000,推荐范围 500-10000(与计算能力有关)
  18. * }} options
  19. * @memberof Genid
  20. */
  21. constructor(options) {
  22. if (options.WorkerId === undefined) {
  23. throw new Error("lost WorkerId");
  24. }
  25. // 1.BaseTime
  26. const BaseTime = 1577836800000;
  27. if (!options.BaseTime || options.BaseTime < 0) {
  28. options.BaseTime = BaseTime;
  29. }
  30. // 2.WorkerIdBitLength
  31. const WorkerIdBitLength = 6;
  32. if (!options.WorkerIdBitLength || options.WorkerIdBitLength < 0) {
  33. options.WorkerIdBitLength = WorkerIdBitLength;
  34. }
  35. // 4.SeqBitLength
  36. const SeqBitLength = 6;
  37. if (!options.SeqBitLength || options.SeqBitLength < 0) {
  38. options.SeqBitLength = SeqBitLength;
  39. }
  40. // 5.MaxSeqNumber
  41. const MaxSeqNumber = (1 << SeqBitLength) - 1;
  42. if (options.MaxSeqNumber <= 0 || options.MaxSeqNumber === undefined) {
  43. options.MaxSeqNumber = MaxSeqNumber;
  44. }
  45. // 6.MinSeqNumber
  46. const MinSeqNumber = 5;
  47. if (!options.MinSeqNumber || options.MinSeqNumber < 0) {
  48. options.MinSeqNumber = MinSeqNumber;
  49. }
  50. // 7.Others
  51. const topOverCostCount = 2000;
  52. if (!options.TopOverCostCount || options.TopOverCostCount < 0) {
  53. options.TopOverCostCount = topOverCostCount;
  54. }
  55. if (options.Method !== 2) {
  56. options.Method = 1;
  57. } else {
  58. options.Method = 2;
  59. }
  60. this.Method = BigInt(options.Method);
  61. this.BaseTime = BigInt(options.BaseTime);
  62. this.WorkerId = BigInt(options.WorkerId);
  63. this.WorkerIdBitLength = BigInt(options.WorkerIdBitLength);
  64. this.SeqBitLength = BigInt(options.SeqBitLength);
  65. this.MaxSeqNumber = BigInt(options.MaxSeqNumber);
  66. this.MinSeqNumber = BigInt(options.MinSeqNumber);
  67. this.TopOverCostCount = BigInt(options.TopOverCostCount);
  68. const timestampShift = this.WorkerIdBitLength + this.SeqBitLength;
  69. const currentSeqNumber = this.MinSeqNumber;
  70. this._TimestampShift = timestampShift;
  71. this._CurrentSeqNumber = currentSeqNumber;
  72. this._LastTimeTick = 0;
  73. this._TurnBackTimeTick = 0;
  74. this._TurnBackIndex = 0;
  75. this._IsOverCost = false;
  76. this._OverCostCountInOneTerm = 0;
  77. }
  78. // DoGenIDAction .
  79. DoGenIdAction(OverCostActionArg) { }
  80. BeginOverCostAction(useTimeTick) { }
  81. EndOverCostAction(useTimeTick) {
  82. // if m1._TermIndex > 10000 {
  83. // m1._TermIndex = 0
  84. // }
  85. }
  86. BeginTurnBackAction(useTimeTick) { }
  87. EndTurnBackAction(useTimeTick) { }
  88. NextOverCostId() {
  89. const currentTimeTick = this.GetCurrentTimeTick();
  90. if (currentTimeTick > this._LastTimeTick) {
  91. // this.EndOverCostAction(currentTimeTick)
  92. this._LastTimeTick = currentTimeTick;
  93. this._CurrentSeqNumber = this.MinSeqNumber;
  94. this._IsOverCost = false;
  95. this._OverCostCountInOneTerm = 0;
  96. // this._GenCountInOneTerm = 0
  97. return this.CalcId(this._LastTimeTick);
  98. }
  99. if (this._OverCostCountInOneTerm >= this.TopOverCostCount) {
  100. // this.EndOverCostAction(currentTimeTick)
  101. this._LastTimeTick = this.GetNextTimeTick();
  102. this._CurrentSeqNumber = this.MinSeqNumber;
  103. this._IsOverCost = false;
  104. this._OverCostCountInOneTerm = 0;
  105. // this._GenCountInOneTerm = 0
  106. return this.CalcId(this._LastTimeTick);
  107. }
  108. if (this._CurrentSeqNumber > this.MaxSeqNumber) {
  109. this._LastTimeTick++;
  110. this._CurrentSeqNumber = this.MinSeqNumber;
  111. this._IsOverCost = true;
  112. this._OverCostCountInOneTerm++;
  113. // this._GenCountInOneTerm++
  114. return this.CalcId(this._LastTimeTick);
  115. }
  116. // this._GenCountInOneTerm++
  117. return this.CalcId(this._LastTimeTick);
  118. }
  119. NextNormalId() {
  120. const currentTimeTick = this.GetCurrentTimeTick();
  121. if (currentTimeTick < this._LastTimeTick) {
  122. if (this._TurnBackTimeTick < 1) {
  123. this._TurnBackTimeTick = this._LastTimeTick - 1;
  124. this._TurnBackIndex++;
  125. // 每毫秒序列数的前 5 位是预留位,0 用于手工新值,1-4 是时间回拨次序
  126. // 支持 4 次回拨次序(避免回拨重叠导致 ID 重复),可无限次回拨(次序循环使用)。
  127. if (this._TurnBackIndex > 4) {
  128. this._TurnBackIndex = 1;
  129. }
  130. this.BeginTurnBackAction(this._TurnBackTimeTick);
  131. }
  132. return this.CalcTurnBackId(this._TurnBackTimeTick);
  133. }
  134. // 时间追平时,_TurnBackTimeTick 清零
  135. if (this._TurnBackTimeTick > 0) {
  136. this.EndTurnBackAction(this._TurnBackTimeTick);
  137. this._TurnBackTimeTick = 0;
  138. }
  139. if (currentTimeTick > this._LastTimeTick) {
  140. this._LastTimeTick = currentTimeTick;
  141. this._CurrentSeqNumber = this.MinSeqNumber;
  142. return this.CalcId(this._LastTimeTick);
  143. }
  144. if (this._CurrentSeqNumber > this.MaxSeqNumber) {
  145. this.BeginOverCostAction(currentTimeTick);
  146. // this._TermIndex++
  147. this._LastTimeTick++;
  148. this._CurrentSeqNumber = this.MinSeqNumber;
  149. this._IsOverCost = true;
  150. this._OverCostCountInOneTerm = 1;
  151. // this._GenCountInOneTerm = 1
  152. return this.CalcId(this._LastTimeTick);
  153. }
  154. return this.CalcId(this._LastTimeTick);
  155. }
  156. CalcId(useTimeTick) {
  157. const result = BigInt(useTimeTick << this._TimestampShift) + BigInt(this.WorkerId << this.SeqBitLength) + BigInt(this._CurrentSeqNumber);
  158. this._CurrentSeqNumber++;
  159. return result;
  160. }
  161. CalcTurnBackId(useTimeTick) {
  162. const result = BigInt(useTimeTick << this._TimestampShift) + BigInt(this.WorkerId << this.SeqBitLength) + BigInt(this._TurnBackIndex);
  163. this._TurnBackTimeTick--;
  164. return result;
  165. }
  166. GetCurrentTimeTick() {
  167. const millis = BigInt((new Date()).valueOf());
  168. return millis - this.BaseTime;
  169. }
  170. GetNextTimeTick() {
  171. let tempTimeTicker = this.GetCurrentTimeTick();
  172. while (tempTimeTicker <= this._LastTimeTick) {
  173. tempTimeTicker = this.GetCurrentTimeTick();
  174. }
  175. return tempTimeTicker;
  176. }
  177. /**
  178. * 生成ID
  179. * @returns 始终输出number类型,超过时throw error
  180. */
  181. NextNumber() {
  182. if (this._IsOverCost) {
  183. //
  184. let id = this.NextOverCostId()
  185. if (id >= 9007199254740992n)
  186. throw Error(`${id.toString()} over max of Number 9007199254740992`)
  187. return parseInt(id.toString())
  188. } else {
  189. //
  190. let id = this.NextNormalId()
  191. if (id >= 9007199254740992n)
  192. throw Error(`${id.toString()} over max of Number 9007199254740992`)
  193. return parseInt(id.toString())
  194. }
  195. }
  196. /**
  197. * 生成ID
  198. * @returns 根据输出数值判断,小于number最大值时输出number类型,大于时输出bigint
  199. */
  200. NextId() {
  201. if (this._IsOverCost) {
  202. let id = this.NextOverCostId()
  203. if (id >= 9007199254740992n)
  204. return id
  205. else
  206. return parseInt(id)
  207. } else {
  208. let id = this.NextNormalId()
  209. if (id >= 9007199254740992n)
  210. return id
  211. else
  212. return parseInt(id)
  213. }
  214. }
  215. /**
  216. * 生成ID
  217. * @returns 始终输出bigint类型
  218. */
  219. NextBigId() {
  220. if (this._IsOverCost) {
  221. //
  222. return this.NextOverCostId()
  223. } else {
  224. //
  225. return this.NextNormalId()
  226. }
  227. }
  228. }
  229. module.exports = Genid;