Files
workspace/code/base-project/base-go/pkg/utils/uid/snowflake.go
T
2025-08-25 17:22:54 +08:00

91 lines
1.8 KiB
Go

package uid
import (
"base-framework/pkg/config"
"sync"
"sync/atomic"
"time"
)
const (
datacenterBits = uint64(5)
workerBits = uint64(5)
sequenceBits = uint64(12)
maxSequence = -1 ^ (-1 << sequenceBits)
workerShift = sequenceBits
datacenterShift = sequenceBits + workerBits
timestampShift = sequenceBits + workerBits + datacenterBits
epoch = int64(1672531200000) // 2023-01-01
)
type Snowflake struct {
lastStamp uint64 // 上一次时间戳 (毫秒)
sequence uint64 // 序列号
dcID uint64
workerID uint64
}
var (
sfInstance *Snowflake
once sync.Once
)
// lazy 初始化实例
func initInstance() {
var dcID, wID uint64
if config.Snowflake != nil {
dcID = config.Snowflake.DatacenterID
wID = config.Snowflake.WorkerID
}
sfInstance = &Snowflake{
dcID: dcID,
workerID: wID,
}
}
// NextID 生成全局唯一 ID,无锁版本
func NextID() uint64 {
once.Do(initInstance)
for {
now := uint64(time.Now().UnixNano() / 1e6)
last := atomic.LoadUint64(&sfInstance.lastStamp)
seq := atomic.LoadUint64(&sfInstance.sequence)
if now < last {
// 系统时钟回拨,等待
now = waitNextMillis(last)
}
if now == last {
seq = (seq + 1) & uint64(maxSequence)
if seq == 0 {
now = waitNextMillis(last)
}
} else {
seq = 0
}
if atomic.CompareAndSwapUint64(&sfInstance.lastStamp, last, now) {
atomic.StoreUint64(&sfInstance.sequence, seq)
id := ((now - uint64(epoch)) << timestampShift) |
(sfInstance.dcID << datacenterShift) |
(sfInstance.workerID << workerShift) |
seq
return id
}
}
}
// 等待下一个毫秒
func waitNextMillis(last uint64) uint64 {
now := uint64(time.Now().UnixNano() / 1e6)
for now <= last {
now = uint64(time.Now().UnixNano() / 1e6)
}
return now
}