-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathsnowFlake.go
59 lines (51 loc) · 1.44 KB
/
snowFlake.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package snowFlake
import (
"errors"
"sync"
"time"
)
// -1 的二进制为 [11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111]
// (-1 << 10) 结果为 [11111111 11111111 11111111 11111111 11111111 11111111 11111100 00000000]
// -1 ^ (-1 << 10) 结果为 [00000000 00000000 00000000 00000000 00000000 00000000 00000011 11111111],十进制为 1023
const (
workerBits uint8 = 10
numberBits uint8 = 12
maxWorker int64 = -1 ^ (-1 << workerBits) // 使用位运算,防止溢出, 1023
maxNumber int64 = -1 ^ (-1 << numberBits) // 4095
timeOffset uint8 = workerBits + numberBits //
workerOffset uint8 = numberBits
startEpoch int64 = 1577932132000
)
type Worker struct {
mu sync.Mutex
timestamp int64
workerId int64
number int64
}
func NewWorker(workerId int64) (*Worker, error) {
if workerId < 0 || workerId > maxWorker {
return nil, errors.New("Worker ID excess of quantity")
}
return &Worker{
timestamp: 0,
workerId: workerId,
number: 0}, nil
}
func (w *Worker) GetId() int64 {
w.mu.Lock()
defer w.mu.Unlock()
now := time.Now().UnixNano()
if w.timestamp == now {
w.number++
if w.number > maxNumber {
for now <= w.timestamp {
now = time.Now().UnixNano() / 1e6
}
}
} else {
w.number = 0
w.timestamp = now
}
ID := int64((now-startEpoch)<<timeOffset | (w.workerId << workerOffset) | (w.number)) //
return ID
}