snowflake.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. package util
  2. import (
  3. "errors"
  4. "fmt"
  5. "sync"
  6. "time"
  7. )
  8. //雪花id生产包
  9. const (
  10. twepoch = int64(1417937700000) // 默认起始的时间戳 1449473700000 。计算时,减去这个值
  11. DistrictIdBits = uint(5) //区域 所占用位置
  12. NodeIdBits = uint(9) //节点 所占位置
  13. sequenceBits = uint(10) //自增ID 所占用位置
  14. /*
  15. * 1 符号位 | 39 时间戳 | 5 区域 | 9 节点 | 10 (毫秒内)自增ID
  16. * 0 | 0000000 00000000 00000000 00000000 00000000 | 00000 | 000000 000 | 000000 0000
  17. *
  18. */
  19. maxNodeId = -1 ^ (-1 << NodeIdBits) //节点 ID 最大范围
  20. maxDistrictId = -1 ^ (-1 << DistrictIdBits) //最大区域范围
  21. nodeIdShift = sequenceBits //左移次数
  22. DistrictIdShift = sequenceBits + NodeIdBits
  23. timestampLeftShift = sequenceBits + NodeIdBits + DistrictIdBits
  24. sequenceMask = -1 ^ (-1 << sequenceBits)
  25. maxNextIdsNum = 100 //单次获取ID的最大数量
  26. )
  27. type IdWorker struct {
  28. sequence int64 //序号
  29. lastTimestamp int64 //最后时间戳
  30. nodeId int64 //节点ID
  31. twepoch int64
  32. districtId int64
  33. mutex sync.Mutex
  34. }
  35. // NewIdWorker new a snowflake id generator object.
  36. func NewIdWorker(NodeId int64) (*IdWorker, error) {
  37. var districtId int64
  38. districtId = 1 //暂时默认给1 ,方便以后扩展
  39. idWorker := &IdWorker{}
  40. if NodeId > maxNodeId || NodeId < 0 {
  41. fmt.Sprintf("NodeId Id can't be greater than %d or less than 0", maxNodeId)
  42. return nil, errors.New(fmt.Sprintf("NodeId Id: %d error", NodeId))
  43. }
  44. if districtId > maxDistrictId || districtId < 0 {
  45. fmt.Sprintf("District Id can't be greater than %d or less than 0", maxDistrictId)
  46. return nil, errors.New(fmt.Sprintf("District Id: %d error", districtId))
  47. }
  48. idWorker.nodeId = NodeId
  49. idWorker.districtId = districtId
  50. idWorker.lastTimestamp = -1
  51. idWorker.sequence = 0
  52. idWorker.twepoch = twepoch
  53. idWorker.mutex = sync.Mutex{}
  54. fmt.Sprintf("worker starting. timestamp left shift %d, District id bits %d, worker id bits %d, sequence bits %d, workerid %d", timestampLeftShift, DistrictIdBits, NodeIdBits, sequenceBits, NodeId)
  55. return idWorker, nil
  56. }
  57. // timeGen generate a unix millisecond.
  58. func timeGen() int64 {
  59. return time.Now().UnixNano() / int64(time.Millisecond)
  60. }
  61. // tilNextMillis spin wait till next millisecond.
  62. func tilNextMillis(lastTimestamp int64) int64 {
  63. timestamp := timeGen()
  64. for timestamp <= lastTimestamp {
  65. timestamp = timeGen()
  66. }
  67. return timestamp
  68. }
  69. // NextId get a snowflake id.
  70. func (id *IdWorker) NextId() (int64, error) {
  71. id.mutex.Lock()
  72. defer id.mutex.Unlock()
  73. return id.nextid()
  74. }
  75. // NextIds get snowflake ids.
  76. func (id *IdWorker) NextIds(num int) ([]int64, error) {
  77. if num > maxNextIdsNum || num < 0 {
  78. fmt.Sprintf("NextIds num can't be greater than %d or less than 0", maxNextIdsNum)
  79. return nil, errors.New(fmt.Sprintf("NextIds num: %d error", num))
  80. }
  81. ids := make([]int64, num)
  82. id.mutex.Lock()
  83. defer id.mutex.Unlock()
  84. for i := 0; i < num; i++ {
  85. ids[i], _ = id.nextid()
  86. }
  87. return ids, nil
  88. }
  89. func (id *IdWorker) nextid() (int64, error) {
  90. timestamp := timeGen()
  91. if timestamp < id.lastTimestamp {
  92. // fmt.Sprintf("clock is moving backwards. Rejecting requests until %d.", id.lastTimestamp)
  93. return 0, errors.New(fmt.Sprintf("Clock moved backwards. Refusing to generate id for %d milliseconds", id.lastTimestamp-timestamp))
  94. }
  95. if id.lastTimestamp == timestamp {
  96. id.sequence = (id.sequence + 1) & sequenceMask
  97. if id.sequence == 0 {
  98. timestamp = tilNextMillis(id.lastTimestamp)
  99. }
  100. } else {
  101. id.sequence = 0
  102. }
  103. id.lastTimestamp = timestamp
  104. return ((timestamp - id.twepoch) << timestampLeftShift) | (id.districtId << DistrictIdShift) | (id.nodeId << nodeIdShift) | id.sequence, nil
  105. }