package snowflake 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 }