snow.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. package utils
  2. import (
  3. "fmt"
  4. "strconv"
  5. "sync"
  6. "time"
  7. )
  8. type Snowflake struct {
  9. epoch int64
  10. timestamp int64
  11. dataCenter int64
  12. workerId int64
  13. sequence int64
  14. mutex sync.Mutex
  15. maxSequence int64
  16. }
  17. const (
  18. epochShift = 22
  19. dataCenterShift = 12
  20. workerIdShift = 10
  21. sequenceShift = 0
  22. sequenceMask = -1 ^ (-1 << sequenceShift)
  23. maxWorkerId = -1 ^ (-1 << workerIdShift)
  24. maxDataCenter = -1 ^ (-1 << dataCenterShift)
  25. )
  26. func NewSnowflake(epoch int64, dataCenter, workerId int64) (*Snowflake, error) {
  27. if dataCenter > maxDataCenter || workerId > maxWorkerId {
  28. return nil, fmt.Errorf("dataCenter or workerId exceeds limit")
  29. }
  30. return &Snowflake{
  31. epoch: epoch,
  32. dataCenter: dataCenter,
  33. workerId: workerId,
  34. maxSequence: -1 ^ (-1 << sequenceShift),
  35. }, nil
  36. }
  37. func (s *Snowflake) NextID() int64 {
  38. s.mutex.Lock()
  39. defer s.mutex.Unlock()
  40. currentTimestamp := time.Now().UnixNano() / 1e6
  41. if s.timestamp == currentTimestamp {
  42. s.sequence = (s.sequence + 1) & sequenceMask
  43. if s.sequence == 0 {
  44. currentTimestamp = s.waitNextTime(currentTimestamp)
  45. }
  46. } else {
  47. s.sequence = 0
  48. }
  49. s.timestamp = currentTimestamp
  50. id := ((currentTimestamp - s.epoch) << epochShift) |
  51. (s.dataCenter << dataCenterShift) |
  52. (s.workerId << workerIdShift) |
  53. s.sequence
  54. return id
  55. }
  56. func (s *Snowflake) waitNextTime(currentTimestamp int64) int64 {
  57. for currentTimestamp <= s.timestamp {
  58. currentTimestamp = time.Now().UnixNano() / 1e6
  59. }
  60. return currentTimestamp
  61. }
  62. var snowflake, _ = NewSnowflake(time.Now().UnixNano()/1e6, 1, 1)
  63. func NextId() int64 {
  64. return snowflake.NextID()
  65. }
  66. func NextIdStr() string {
  67. return strconv.FormatInt(NextId(), 10)
  68. }