66 lines
1.2 KiB
Go
66 lines
1.2 KiB
Go
|
package util
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"sync"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
// MaxSequence max sequence in one time
|
||
|
MaxSequence = 1000
|
||
|
// WorkerBit worker bit
|
||
|
WorkerBit = 10
|
||
|
// SequenceBit sequence bit
|
||
|
SequenceBit = 10
|
||
|
)
|
||
|
|
||
|
// SnowFlake snow flake
|
||
|
type SnowFlake struct {
|
||
|
sync.Mutex
|
||
|
lastTimestamp int64
|
||
|
sequence int64
|
||
|
workerID int64
|
||
|
}
|
||
|
|
||
|
// NewSnowFlake new
|
||
|
func NewSnowFlake() *SnowFlake {
|
||
|
return &SnowFlake{
|
||
|
workerID: time.Now().UnixNano() % 1000,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Generate generate
|
||
|
func (s *SnowFlake) Generate() (int64, error) {
|
||
|
s.Lock()
|
||
|
defer s.Unlock()
|
||
|
|
||
|
now := time.Now().UnixNano() / 1e6
|
||
|
if now == s.lastTimestamp {
|
||
|
s.sequence = (s.sequence + 1) % MaxSequence
|
||
|
if s.sequence == 0 {
|
||
|
now = s.waitNextMill(now)
|
||
|
}
|
||
|
} else {
|
||
|
s.sequence = 0
|
||
|
}
|
||
|
|
||
|
if now < s.lastTimestamp {
|
||
|
return 0, errors.New("inner time error")
|
||
|
}
|
||
|
s.lastTimestamp = now
|
||
|
return s.generate() % 1000000000, nil
|
||
|
}
|
||
|
|
||
|
func (s *SnowFlake) generate() int64 {
|
||
|
return (s.lastTimestamp << (WorkerBit + SequenceBit)) | (s.workerID << SequenceBit) | s.sequence
|
||
|
}
|
||
|
|
||
|
func (s *SnowFlake) waitNextMill(t int64) int64 {
|
||
|
for t == s.lastTimestamp {
|
||
|
time.Sleep(100 * time.Microsecond)
|
||
|
t = time.Now().UnixNano() / 1e6
|
||
|
}
|
||
|
return t
|
||
|
}
|