You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
1.9 KiB
106 lines
1.9 KiB
package snow
|
|
|
|
import (
|
|
"errors"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
var OrderWorker *Worker
|
|
var AfsWorker *Worker
|
|
var UserWorker *Worker
|
|
var once sync.Once
|
|
|
|
func GetOrderWorker() *Worker {
|
|
once.Do(func() {
|
|
OrderWorker = NewWorker(1, 1)
|
|
})
|
|
return OrderWorker
|
|
}
|
|
|
|
func GetAfsWorker() *Worker {
|
|
once.Do(func() {
|
|
AfsWorker = NewWorker(1, 2)
|
|
})
|
|
return AfsWorker
|
|
}
|
|
|
|
func GetUserWorker() *Worker {
|
|
once.Do(func() {
|
|
UserWorker = NewWorker(1, 3)
|
|
})
|
|
return UserWorker
|
|
}
|
|
|
|
const (
|
|
workerIDBits = uint64(4)
|
|
businessIDBits = uint64(4)
|
|
sequenceBits = uint64(14)
|
|
|
|
maxWorkerID = int64(-1) ^ (int64(-1) << workerIDBits)
|
|
maxBusinessID = int64(-1) ^ (int64(-1) << businessIDBits)
|
|
maxSequence = int64(-1) ^ (int64(-1) << sequenceBits)
|
|
|
|
timeLeft = uint8(22) // 6 + 4 + 12
|
|
workLeft = uint8(18) // 4 + 12
|
|
businessLeft = uint(14) // 12
|
|
|
|
initialisierung = int64(1638935759)
|
|
)
|
|
|
|
type Worker struct {
|
|
mu sync.Mutex
|
|
LastStamp int64
|
|
WorkerID int64
|
|
BusinessID int64
|
|
Sequence int64 // 当前毫秒已经生成的ID序列号(从0 开始累加) 1毫秒内最多生成4096个ID
|
|
}
|
|
|
|
func NewWorker(workerID, businessID int64) *Worker {
|
|
return &Worker{
|
|
WorkerID: workerID,
|
|
LastStamp: 0,
|
|
Sequence: 0,
|
|
BusinessID: businessID,
|
|
}
|
|
}
|
|
|
|
func (w *Worker) getMilliSeconds() int64 {
|
|
return time.Now().Unix()
|
|
}
|
|
|
|
func (w *Worker) NextID() (uint64, error) {
|
|
w.mu.Lock()
|
|
defer w.mu.Unlock()
|
|
|
|
return w.nextID()
|
|
}
|
|
|
|
func (w *Worker) nextID() (uint64, error) {
|
|
timeStamp := w.getMilliSeconds()
|
|
if timeStamp < w.LastStamp {
|
|
return 0, errors.New("time is moving backwards,waiting until")
|
|
}
|
|
|
|
if w.LastStamp == timeStamp {
|
|
|
|
w.Sequence = (w.Sequence + 1) & maxSequence
|
|
|
|
if w.Sequence == 0 {
|
|
for timeStamp <= w.LastStamp {
|
|
timeStamp = w.getMilliSeconds()
|
|
}
|
|
}
|
|
} else {
|
|
w.Sequence = 0
|
|
}
|
|
|
|
w.LastStamp = timeStamp
|
|
id := ((timeStamp - initialisierung) << timeLeft) |
|
|
(w.WorkerID << workLeft) |
|
|
(w.BusinessID << businessLeft) |
|
|
w.Sequence
|
|
|
|
return uint64(id), nil
|
|
}
|