uuid.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. package utils
  2. import (
  3. "errors"
  4. "fmt"
  5. "sync"
  6. "time"
  7. )
  8. func SetUuidNode(i int) {
  9. newUuid().setNodeId(i)
  10. }
  11. func UuidPrefix(pix string) string {
  12. return fmt.Sprintf("%s%d", pix, GenUuid())
  13. }
  14. func GenUuid() int64 {
  15. for i := 0; i < 3; i++ {
  16. uuid, err := newUuid().generateId()
  17. if err == nil {
  18. return uuid
  19. }
  20. }
  21. return time.Now().UnixMilli()
  22. }
  23. func UuidToTime(uuid int64) time.Time {
  24. return newUuid().uuidToTime(uuid)
  25. }
  26. func TimeToUuid(ts time.Time) int64 {
  27. return newUuid().timeToUuid(ts)
  28. }
  29. var (
  30. rotateId = 15
  31. nodeId = 6
  32. T2018 int64 = 1514736000000
  33. )
  34. type Uuid struct {
  35. lock sync.Mutex
  36. timeId int64
  37. nodeId int
  38. rotateId int
  39. nodeIdWidth int
  40. nodeIdMask int
  41. rotateIdWidth int
  42. rotateIdMask int
  43. T201801010000 int64
  44. }
  45. var midUtil *Uuid
  46. func newUuid() *Uuid {
  47. if midUtil == nil {
  48. midUtil = &Uuid{
  49. timeId: 0,
  50. lock: sync.Mutex{},
  51. nodeIdWidth: nodeId,
  52. nodeIdMask: 0x3F,
  53. rotateIdWidth: rotateId,
  54. rotateIdMask: 0x7FFF,
  55. T201801010000: T2018,
  56. nodeId: 0,
  57. }
  58. }
  59. return midUtil
  60. }
  61. func (m *Uuid) setNodeId(i int) {
  62. m.nodeId = i
  63. return
  64. }
  65. func (m *Uuid) generateId() (int64, error) {
  66. m.lock.Lock()
  67. defer m.lock.Unlock()
  68. m.rotateId = (m.rotateId + 1) & m.rotateIdMask
  69. mid := time.Now().UnixMilli() - m.T201801010000
  70. if mid > m.timeId {
  71. m.timeId = mid
  72. m.rotateId = 1
  73. } else if mid == m.timeId {
  74. if m.rotateId == (m.rotateIdMask - 1) {
  75. for {
  76. if mid <= m.timeId {
  77. mid = time.Now().UnixMilli() - m.T201801010000
  78. } else {
  79. return m.generateId()
  80. }
  81. }
  82. }
  83. } else {
  84. if m.rotateId > (m.rotateIdMask-1)*9/10 {
  85. if m.timeId-mid < 3000 {
  86. for {
  87. if mid < m.timeId {
  88. mid = time.Now().UnixMilli() - m.T201801010000
  89. }
  90. return m.generateId()
  91. }
  92. } else {
  93. return 0, errors.New(fmt.Sprintf("Time turn back %d ms, it too long!!!", m.timeId-mid))
  94. }
  95. } else {
  96. mid = m.timeId
  97. }
  98. }
  99. mid <<= m.nodeIdWidth
  100. mid += int64(m.nodeId & m.nodeIdMask)
  101. mid <<= m.rotateIdWidth
  102. mid += int64(m.rotateId)
  103. return mid, nil
  104. }
  105. func (m *Uuid) uuidToTime(uuid int64) time.Time {
  106. uuid >>= m.nodeId + m.rotateId
  107. dateNum := uuid + T2018
  108. return time.UnixMilli(dateNum)
  109. }
  110. func (m *Uuid) timeToUuid(ts time.Time) int64 {
  111. m.lock.Lock()
  112. defer m.lock.Unlock()
  113. m.rotateId = (m.rotateId + 1) & m.rotateIdMask
  114. mid := ts.UnixMilli() - m.T201801010000
  115. mid <<= m.nodeIdWidth
  116. mid += int64(m.nodeId & m.nodeIdMask)
  117. mid <<= m.rotateIdWidth
  118. mid += int64(m.rotateId)
  119. return mid
  120. }