61 lines
1.3 KiB
Go
61 lines
1.3 KiB
Go
package utils
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// Snowflake 雪花ID生成器
|
|
// 64位布局: 41位时间戳 + 10位机器ID + 12位序列号
|
|
// 生成约19位数字, 前端用字符串表示避免精度丢失
|
|
type Snowflake struct {
|
|
mu sync.Mutex
|
|
epoch int64 // 自定义纪元(毫秒)
|
|
machineID int64 // 机器ID (0-1023)
|
|
sequence int64 // 序列号 (0-4095)
|
|
lastTime int64 // 上次生成ID的时间戳
|
|
}
|
|
|
|
var sf *Snowflake
|
|
|
|
func init() {
|
|
sf = NewSnowflake(1704067200000, 1) // 2024-01-01 00:00:00 UTC 作为纪元
|
|
}
|
|
|
|
func NewSnowflake(epoch int64, machineID int64) *Snowflake {
|
|
return &Snowflake{
|
|
epoch: epoch,
|
|
machineID: machineID & 0x3FF, // 10位, 最大1023
|
|
}
|
|
}
|
|
|
|
// NextID 生成下一个唯一ID
|
|
func (s *Snowflake) NextID() uint64 {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
|
|
now := time.Now().UnixMilli() - s.epoch
|
|
|
|
if now == s.lastTime {
|
|
s.sequence = (s.sequence + 1) & 0xFFF // 12位, 最大4095
|
|
if s.sequence == 0 {
|
|
// 序列号溢出, 等待下一毫秒
|
|
for now <= s.lastTime {
|
|
now = time.Now().UnixMilli() - s.epoch
|
|
}
|
|
}
|
|
} else {
|
|
s.sequence = 0
|
|
}
|
|
|
|
s.lastTime = now
|
|
|
|
// 组装ID: 时间戳左移22位 + 机器ID左移12位 + 序列号
|
|
return uint64(now)<<22 | uint64(s.machineID)<<12 | uint64(s.sequence)
|
|
}
|
|
|
|
// GenID 全局便捷方法
|
|
func GenID() uint64 {
|
|
return sf.NextID()
|
|
}
|