snowflake.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. package util
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/spf13/viper"
  6. "sync"
  7. "time"
  8. )
  9. type SnowFlakeIdWorker struct {
  10. // 开始时间戳
  11. twepoch int64
  12. // 机器ID所占的位数
  13. workerIdBits int64
  14. // 数据标识ID所占的位数
  15. dataCenterIdBits int64
  16. // 支持的最大机器ID
  17. maxWorkerId int64
  18. // 支持的最大机房 ID
  19. maxDataCenterId int64
  20. // 序列在ID中占的位数
  21. sequenceBits int64
  22. // 机器ID向左移位数
  23. workerIdShift int64
  24. // 机房ID向左移位数
  25. dataCenterIdShift int64
  26. // 时间截向左移位数
  27. timestampLeftShift int64
  28. // 生成序列的掩码最大值
  29. sequenceMask int64
  30. // 工作机器ID
  31. workerId int64
  32. // 机房ID
  33. dataCenterId int64
  34. /**
  35. * 毫秒内序列
  36. */
  37. sequence int64
  38. // 上次生成ID的时间戳
  39. lastTimestamp int64
  40. // 锁
  41. lock sync.Mutex
  42. }
  43. func (p *SnowFlakeIdWorker) init(dataCenterId int64, workerId int64) {
  44. t, _ := time.Parse("2006-01-02", viper.GetString("time.time"))
  45. // 开始时间戳;这里是2021-06-01
  46. p.twepoch = t.Unix()
  47. // 机器ID所占的位数
  48. p.workerIdBits = 5
  49. // 数据标识ID所占的位数
  50. p.dataCenterIdBits = 5
  51. // 支持的最大机器ID,最大是31
  52. p.maxWorkerId = -1 ^ (-1 << p.workerIdBits)
  53. // 支持的最大机房ID,最大是 31
  54. p.maxDataCenterId = -1 ^ (-1 << p.dataCenterIdBits)
  55. // 序列在ID中占的位数
  56. p.sequenceBits = 12
  57. // 机器ID向左移12位
  58. p.workerIdShift = p.sequenceBits
  59. // 机房ID向左移17位
  60. p.dataCenterIdShift = p.sequenceBits + p.workerIdBits
  61. // 时间截向左移22位
  62. p.timestampLeftShift = p.sequenceBits + p.workerIdBits + p.dataCenterIdBits
  63. // 生成序列的掩码最大值,最大为4095
  64. p.sequenceMask = -1 ^ (-1 << p.sequenceBits)
  65. if workerId > p.maxWorkerId || workerId < 0 {
  66. panic(errors.New(fmt.Sprintf("Worker ID can't be greater than %d or less than 0", p.maxWorkerId)))
  67. }
  68. if dataCenterId > p.maxDataCenterId || dataCenterId < 0 {
  69. panic(errors.New(fmt.Sprintf("DataCenter ID can't be greater than %d or less than 0", p.maxDataCenterId)))
  70. }
  71. p.workerId = workerId
  72. p.dataCenterId = dataCenterId
  73. // 毫秒内序列(0~4095)
  74. p.sequence = 0
  75. // 上次生成 ID 的时间戳
  76. p.lastTimestamp = -1
  77. }
  78. // 生成ID,注意此方法已经通过加锁来保证线程安全
  79. func (p *SnowFlakeIdWorker) nextId() int64 {
  80. p.lock.Lock()
  81. defer p.lock.Unlock()
  82. timestamp := p.timeGen()
  83. // 如果当前时间小于上一次 ID 生成的时间戳,说明发生时钟回拨,为保证ID不重复抛出异常。
  84. if timestamp < p.lastTimestamp {
  85. panic(errors.New(fmt.Sprintf("Clock moved backwards. Refusing to generate id for %d milliseconds", p.lastTimestamp-timestamp)))
  86. }
  87. if p.lastTimestamp == timestamp {
  88. // 同一时间生成的,则序号+1
  89. p.sequence = (p.sequence + 1) & p.sequenceMask
  90. // 毫秒内序列溢出:超过最大值
  91. if p.sequence == 0 {
  92. // 阻塞到下一个毫秒,获得新的时间戳
  93. timestamp = p.tilNextMillis(p.lastTimestamp)
  94. }
  95. } else {
  96. // 时间戳改变,序列重置
  97. p.sequence = 0
  98. }
  99. // 保存本次的时间戳
  100. p.lastTimestamp = timestamp
  101. // 移位并通过或运算拼到一起
  102. return ((timestamp - p.twepoch) << p.timestampLeftShift) |
  103. (p.dataCenterId << p.dataCenterIdShift) |
  104. (p.workerId << p.workerIdShift) | p.sequence
  105. }
  106. func (p *SnowFlakeIdWorker) tilNextMillis(lastTimestamp int64) int64 {
  107. timestamp := p.timeGen()
  108. for timestamp <= lastTimestamp {
  109. timestamp = p.timeGen()
  110. }
  111. return timestamp
  112. }
  113. func (p *SnowFlakeIdWorker) timeGen() int64 {
  114. return time.Now().UnixNano() / 1e6
  115. }
  116. func GetID() int64 {
  117. idWorker := &SnowFlakeIdWorker{}
  118. idWorker.init(0, 1)
  119. return idWorker.nextId()
  120. }