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

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
}