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.

snowflakeIdv1.ts 13 kB

2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. import { snowflakeIdv1Option } from "./snowflakeIdv1Option"
  2. /**
  3. *
  4. */
  5. export class snowflakeIdv1 {
  6. /**
  7. * 雪花计算方法,(1-漂移算法|2-传统算法),默认 1
  8. */
  9. private Method
  10. /**
  11. * 基础时间(ms 单位),不能超过当前系统时间
  12. */
  13. private BaseTime
  14. /**
  15. * 机器码,必须由外部设定,最大值 2^WorkerIdBitLength-1
  16. */
  17. private WorkerId
  18. /**
  19. * 机器码位长,默认值 6,取值范围 [1, 15](要求:序列数位长+机器码位长不超过 22)
  20. */
  21. private WorkerIdBitLength
  22. /**
  23. * 序列数位长,默认值 6,取值范围 [3, 21](要求:序列数位长+机器码位长不超过 22)
  24. */
  25. private SeqBitLength
  26. /**
  27. * 最大序列数(含),设置范围 [MinSeqNumber, 2^SeqBitLength-1],默认值 0,表示最大序列数取最大值(2^SeqBitLength-1])
  28. */
  29. private MaxSeqNumber
  30. /**
  31. * 最小序列数(含),默认值 5,取值范围 [5, MaxSeqNumber],每毫秒的前 5 个序列数对应编号 0-4 是保留位,其中 1-4 是时间回拨相应预留位,0 是手工新值预留位
  32. */
  33. private MinSeqNumber
  34. /**
  35. * 最大漂移次数(含),默认 2000,推荐范围 500-10000(与计算能力有关)
  36. */
  37. private TopOverCostCount
  38. /**
  39. *
  40. */
  41. private _TimestampShift
  42. /**
  43. *
  44. */
  45. private _CurrentSeqNumber
  46. /**
  47. *
  48. */
  49. private _LastTimeTick: bigint
  50. /**
  51. * 回拨次序, 支持 4 次回拨次序(避免回拨重叠导致 ID 重复)
  52. */
  53. private _TurnBackTimeTick: bigint
  54. /**
  55. *
  56. */
  57. private _TurnBackIndex
  58. /**
  59. *
  60. */
  61. private _IsOverCost
  62. /**
  63. *
  64. */
  65. private _OverCostCountInOneTerm
  66. /**
  67. *Creates an instance of Genid.
  68. * @author zhupengfeivip
  69. * @param {{
  70. * BaseTime: 1577836800000, // 基础时间(ms 单位),默认2020年1月1日,不能超过当前系统时间,一旦投入使用就不能再更改,更改后产生的ID可能会和以前的重复
  71. * WorkerId: Number, // 机器码,必须由外部设定,最大值 2^WorkerIdBitLength-1
  72. * WorkerIdBitLength: 6, // 机器码位长,默认值 6,取值范围 [1, 15](要求:序列数位长+机器码位长不超过 22)
  73. * SeqBitLength: 6, // 序列数位长,默认值 6,取值范围 [3, 21](要求:序列数位长+机器码位长不超过 22)
  74. * MaxSeqNumber: 5, // 最大序列数(含),设置范围 [MinSeqNumber, 2^SeqBitLength-1],默认值 0,表示最大序列数取最大值(2^SeqBitLength-1])
  75. * MinSeqNumber: 5, // 最小序列数(含),默认值 5,取值范围 [5, MaxSeqNumber],每毫秒的前 5 个序列数对应编号 0-4 是保留位,其中 1-4 是时间回拨相应预留位,0 是手工新值预留位
  76. * TopOverCostCount: 2000// 最大漂移次数(含),默认 2000,推荐范围 500-10000(与计算能力有关)
  77. * }} options
  78. * @memberof Genid
  79. */
  80. constructor(options: snowflakeIdv1Option) {
  81. if (options.workerId === undefined)
  82. throw new Error("lost WorkerId")
  83. // 1.BaseTime 2020年1月1日 Wed, 01 Jan 2020 00:00:00 GMT 0时区的2020年1月1日
  84. const BaseTime = 1577836800000
  85. if (!options.baseTime || options.baseTime < 0)
  86. options.baseTime = BaseTime
  87. // 2.WorkerIdBitLength
  88. const WorkerIdBitLength = 6
  89. if (!options.workerIdBitLength || options.workerIdBitLength < 0)
  90. options.workerIdBitLength = WorkerIdBitLength
  91. // 4.SeqBitLength
  92. const SeqBitLength = 6
  93. if (!options.seqBitLength || options.seqBitLength < 0)
  94. options.seqBitLength = SeqBitLength
  95. // 5.MaxSeqNumber
  96. if (options.maxSeqNumber == undefined || options.maxSeqNumber <= 0)
  97. options.maxSeqNumber = (1 << SeqBitLength) - 1
  98. // 6.MinSeqNumber
  99. const MinSeqNumber = 5
  100. if (options.minSeqNumber == undefined || options.minSeqNumber < 0)
  101. options.minSeqNumber = MinSeqNumber
  102. // 7.Others
  103. const topOverCostCount = 2000
  104. if (options.topOverCostCount == undefined || options.topOverCostCount < 0)
  105. options.topOverCostCount = topOverCostCount
  106. if (options.method !== 2)
  107. options.method = 1
  108. else
  109. options.method = 2
  110. this.Method = BigInt(options.method)
  111. this.BaseTime = BigInt(options.baseTime)
  112. this.WorkerId = BigInt(options.workerId)
  113. this.WorkerIdBitLength = BigInt(options.workerIdBitLength)
  114. this.SeqBitLength = BigInt(options.seqBitLength)
  115. this.MaxSeqNumber = BigInt(options.maxSeqNumber)
  116. this.MinSeqNumber = BigInt(options.minSeqNumber)
  117. this.TopOverCostCount = BigInt(options.topOverCostCount)
  118. const timestampShift = this.WorkerIdBitLength + this.SeqBitLength
  119. const currentSeqNumber = this.MinSeqNumber
  120. this._TimestampShift = timestampShift
  121. this._CurrentSeqNumber = currentSeqNumber
  122. this._LastTimeTick = BigInt(0)
  123. this._TurnBackTimeTick = BigInt(0)
  124. this._TurnBackIndex = 0
  125. this._IsOverCost = false
  126. this._OverCostCountInOneTerm = 0
  127. }
  128. /**
  129. * 当前序列号超过最大范围,开始透支使用序号号的通知事件,,本项暂未实现
  130. * @returns
  131. */
  132. private BeginOverCostAction(useTimeTick: any) {
  133. }
  134. /**
  135. * 当前序列号超过最大范围,结束透支使用序号号的通知事件,,本项暂未实现
  136. * @returns
  137. */
  138. private EndOverCostAction(useTimeTick: any) {
  139. // if m1._TermIndex > 10000 {
  140. // m1._TermIndex = 0
  141. // }
  142. }
  143. /**
  144. * 开始时间回拨通知,本项暂未实现
  145. * @returns
  146. */
  147. private BeginTurnBackAction(useTimeTick: any) {
  148. }
  149. /**
  150. * 结束时间回拨通知,本项暂未实现
  151. * @returns
  152. */
  153. private EndTurnBackAction(useTimeTick: any) {
  154. }
  155. /**
  156. * 雪花漂移算法
  157. * @returns
  158. */
  159. private NextOverCostId(): bigint {
  160. const currentTimeTick = this.GetCurrentTimeTick()
  161. if (currentTimeTick > this._LastTimeTick) {
  162. this.EndOverCostAction(currentTimeTick)
  163. //当前时间大于上次时间,说明是时间是递增的,这是正常情况
  164. this._LastTimeTick = currentTimeTick
  165. this._CurrentSeqNumber = this.MinSeqNumber
  166. this._IsOverCost = false
  167. this._OverCostCountInOneTerm = 0
  168. // this._GenCountInOneTerm = 0
  169. return this.CalcId(this._LastTimeTick)
  170. }
  171. if (this._OverCostCountInOneTerm >= this.TopOverCostCount) {
  172. //当前漂移次数超过最大限制
  173. // TODO: 在漂移终止,等待时间对齐时,如果发生时间回拨较长,则此处可能等待较长时间。可优化为:在漂移终止时增加时间回拨应对逻辑。(该情况发生概率很低)
  174. this.EndOverCostAction(currentTimeTick)
  175. this._LastTimeTick = this.GetNextTimeTick()
  176. this._CurrentSeqNumber = this.MinSeqNumber
  177. this._IsOverCost = false
  178. this._OverCostCountInOneTerm = 0
  179. // this._GenCountInOneTerm = 0
  180. return this.CalcId(this._LastTimeTick)
  181. }
  182. if (this._CurrentSeqNumber > this.MaxSeqNumber) {
  183. //当前序列数超过最大限制,则要提前透支
  184. this._LastTimeTick++
  185. this._CurrentSeqNumber = this.MinSeqNumber
  186. this._IsOverCost = true
  187. this._OverCostCountInOneTerm++
  188. // this._GenCountInOneTerm++
  189. return this.CalcId(this._LastTimeTick)
  190. }
  191. // this._GenCountInOneTerm++
  192. return this.CalcId(this._LastTimeTick)
  193. }
  194. /**
  195. * 常规雪花算法
  196. * @returns
  197. */
  198. private NextNormalId() {
  199. const currentTimeTick = this.GetCurrentTimeTick()
  200. if (currentTimeTick < this._LastTimeTick) {
  201. if (this._TurnBackTimeTick < 1) {
  202. this._TurnBackTimeTick = this._LastTimeTick - BigInt(1)
  203. this._TurnBackIndex++
  204. // 每毫秒序列数的前 5 位是预留位,0 用于手工新值,1-4 是时间回拨次序
  205. // 支持 4 次回拨次序(避免回拨重叠导致 ID 重复),可无限次回拨(次序循环使用)。
  206. if (this._TurnBackIndex > 4)
  207. this._TurnBackIndex = 1
  208. this.BeginTurnBackAction(this._TurnBackTimeTick)
  209. }
  210. return this.CalcTurnBackId(this._TurnBackTimeTick)
  211. }
  212. // 时间追平时,_TurnBackTimeTick 清零
  213. if (this._TurnBackTimeTick > 0) {
  214. this.EndTurnBackAction(this._TurnBackTimeTick)
  215. this._TurnBackTimeTick = BigInt(0)
  216. }
  217. if (currentTimeTick > this._LastTimeTick) {
  218. this._LastTimeTick = currentTimeTick
  219. this._CurrentSeqNumber = this.MinSeqNumber
  220. return this.CalcId(this._LastTimeTick)
  221. }
  222. if (this._CurrentSeqNumber > this.MaxSeqNumber) {
  223. this.BeginOverCostAction(currentTimeTick)
  224. // this._TermIndex++
  225. this._LastTimeTick++
  226. this._CurrentSeqNumber = this.MinSeqNumber
  227. this._IsOverCost = true
  228. this._OverCostCountInOneTerm = 1
  229. // this._GenCountInOneTerm = 1
  230. return this.CalcId(this._LastTimeTick)
  231. }
  232. return this.CalcId(this._LastTimeTick)
  233. }
  234. /**
  235. * 生成ID
  236. * @param useTimeTick 时间戳
  237. * @returns
  238. */
  239. private CalcId(useTimeTick: bigint) {
  240. //ID组成 1.相对基础时间的时间差 | 2.WorkerId | 3.序列数
  241. //时间差,是生成ID时的系统时间减去 BaseTime 的总时间差(毫秒单位)
  242. const result = BigInt(useTimeTick << this._TimestampShift) + BigInt(this.WorkerId << this.SeqBitLength) + BigInt(this._CurrentSeqNumber)
  243. this._CurrentSeqNumber++
  244. return result
  245. }
  246. /**
  247. * 生成时间回拨ID
  248. * @returns
  249. */
  250. private CalcTurnBackId(useTimeTick: any) {
  251. const result = BigInt(useTimeTick << this._TimestampShift) + BigInt(this.WorkerId << this.SeqBitLength) + BigInt(this._TurnBackIndex)
  252. this._TurnBackTimeTick--
  253. return result
  254. }
  255. /**
  256. *
  257. * @returns
  258. */
  259. private GetCurrentTimeTick() {
  260. const millis = BigInt((new Date()).valueOf())
  261. return millis - this.BaseTime
  262. }
  263. /**
  264. *
  265. * @returns
  266. */
  267. private GetNextTimeTick() {
  268. let tempTimeTicker = this.GetCurrentTimeTick()
  269. while (tempTimeTicker <= this._LastTimeTick) {
  270. tempTimeTicker = this.GetCurrentTimeTick()
  271. }
  272. return tempTimeTicker
  273. }
  274. /**
  275. * 生成ID
  276. * @returns 始终输出number类型,超过时throw error
  277. */
  278. public NextNumber(): number {
  279. if (this._IsOverCost) {
  280. //
  281. let id = this.NextOverCostId()
  282. if (id >= 9007199254740992n)
  283. throw Error(`${id.toString()} over max of Number 9007199254740992`)
  284. return parseInt(id.toString())
  285. } else {
  286. //
  287. let id = this.NextNormalId()
  288. if (id >= 9007199254740992n)
  289. throw Error(`${id.toString()} over max of Number 9007199254740992`)
  290. return parseInt(id.toString())
  291. }
  292. }
  293. /**
  294. * 生成ID
  295. * @returns 根据输出数值判断,小于number最大值时输出number类型,大于时输出bigint
  296. */
  297. public NextId(): number | bigint {
  298. if (this._IsOverCost) {
  299. //
  300. let id = this.NextOverCostId()
  301. if (id >= 9007199254740992n)
  302. return id
  303. else
  304. return parseInt(id.toString())
  305. } else {
  306. //
  307. let id = this.NextNormalId()
  308. if (id >= 9007199254740992n)
  309. return id
  310. else
  311. return parseInt(id.toString())
  312. }
  313. }
  314. /**
  315. * 生成ID
  316. * @returns 始终输出bigint类型
  317. */
  318. public NextBigId(): bigint {
  319. if (this._IsOverCost) {
  320. //
  321. return this.NextOverCostId()
  322. } else {
  323. //
  324. return this.NextNormalId()
  325. }
  326. }
  327. }