refactor(utils): 移除第三方雪花算法依赖,实现自定义Snowflake生成器并修复cronex递归调用问题
This commit is contained in:
@@ -7,8 +7,6 @@ import (
|
||||
|
||||
"github.com/antlabs/cronex"
|
||||
"github.com/gogf/gf/v2/os/glog"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"github.com/yitter/idgenerator-go/idgen"
|
||||
sensitive "github.com/zmexing/go-sensitive-word"
|
||||
)
|
||||
|
||||
@@ -27,17 +25,20 @@ func init() {
|
||||
// 创建 IdGeneratorOptions 对象,可在构造函数中输入 WorkerId:
|
||||
Loger.SetFlags(glog.F_TIME_STD | glog.F_FILE_LONG) //设置flag
|
||||
Loger.Print(ctx, "初始化日志")
|
||||
tt := gconv.Uint16(1)
|
||||
var options = idgen.NewIdGeneratorOptions(tt)
|
||||
// tt := gconv.Uint16(1)
|
||||
// var options = idgen.NewIdGeneratorOptions(tt)
|
||||
// options.SeqBitLength = 4
|
||||
// options.WorkerIdBitLength = 10 // 默认值6,限定 WorkerId 最大值为2^6-1,即默认最多支持64个节点。
|
||||
// options.SeqBitLength = 6; // 默认值6,限制每毫秒生成的ID个数。若生成速度超过5万个/秒,建议加大 SeqBitLength 到 10。
|
||||
// options.BaseTime = Your_Base_Time // 如果要兼容老系统的雪花算法,此处应设置为老系统的BaseTime。
|
||||
// ...... 其它参数参考 IdGeneratorOptions 定义。
|
||||
|
||||
// 保存参数(务必调用,否则参数设置不生效):
|
||||
idgen.SetIdGenerator(options)
|
||||
newId := idgen.NextId()
|
||||
glog.Debug(context.Background(), "初始化雪花算法", newId)
|
||||
// // 保存参数(务必调用,否则参数设置不生效):
|
||||
// idgen.SetIdGenerator(options)
|
||||
// newId := idgen.NextId()
|
||||
// glog.Debug(context.Background(), "初始化雪花算法", newId)
|
||||
glog.Debug(context.Background(), "初始化雪花算法", utils.DefaultGenerator.Get())
|
||||
|
||||
Filter, _ = sensitive.NewFilter(
|
||||
sensitive.StoreOption{Type: sensitive.StoreMemory}, // 基于内存
|
||||
sensitive.FilterOption{Type: sensitive.FilterDfa}, // 基于DFA算法
|
||||
|
||||
@@ -37,10 +37,10 @@ func (c *Cronex) AddFunc(spec string, cmd func()) (node TimerNoder, err error) {
|
||||
|
||||
// 运行消费者循环
|
||||
func (c *Cronex) Run() {
|
||||
c.Run()
|
||||
c.Timer.Run()
|
||||
}
|
||||
|
||||
// 关闭cronex的任务循环
|
||||
func (c *Cronex) Stop() {
|
||||
c.Stop()
|
||||
c.Timer.Stop()
|
||||
}
|
||||
|
||||
149
common/utils/snowflake.go
Normal file
149
common/utils/snowflake.go
Normal file
@@ -0,0 +1,149 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Snowflake is a uint32-sized ID with 32 node support and 8.5 year lifespan
|
||||
type Snowflake uint32
|
||||
|
||||
// ID is an alias for Snowflake
|
||||
type ID = Snowflake
|
||||
|
||||
func (s Snowflake) String() string {
|
||||
return strconv.FormatUint(uint64(s), 16)
|
||||
}
|
||||
|
||||
// ParseSnowflake parses a string into a snowflake, if possible
|
||||
func ParseSnowflake(s string) (Snowflake, error) {
|
||||
i, err := strconv.ParseUint(s, 16, 32)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return Snowflake(i), nil
|
||||
}
|
||||
|
||||
// DefaultGenerator is a Generator with the epoch set to Jan 1, 2025 UTC
|
||||
var DefaultGenerator = NewGen(time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC), 0)
|
||||
|
||||
// Generator holds info needed for generating snowflakes with 32 node support
|
||||
type Generator struct {
|
||||
Epoch time.Time
|
||||
nodeID uint8 // 0-31 (5位,支持32个节点)
|
||||
sequence uint8 // 0-255 (8位,支持每秒256个ID)
|
||||
lastSec uint32 // 上次生成ID的秒级时间戳
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// NewGen returns a new generator with specified epoch and node ID
|
||||
func NewGen(epoch time.Time, nodeID uint8) *Generator {
|
||||
if nodeID >= 32 { // 5位最多支持0-31
|
||||
panic(errors.New("node ID must be between 0 and 31"))
|
||||
}
|
||||
return &Generator{
|
||||
Epoch: epoch,
|
||||
nodeID: nodeID,
|
||||
}
|
||||
}
|
||||
|
||||
// Get generates a new unique snowflake ID and returns it as uint32
|
||||
func (g *Generator) Get() uint32 {
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
|
||||
// 获取当前时间戳(自纪元以来的秒数)
|
||||
now := time.Now()
|
||||
sec := uint32(now.Sub(g.Epoch).Seconds())
|
||||
|
||||
// 检查时间戳是否超出28位限制 (2^28 - 1 = 268435455秒 ≈ 8.5年)
|
||||
if sec >= (1 << 28) {
|
||||
panic(errors.New("timestamp overflow: please update epoch"))
|
||||
}
|
||||
|
||||
// 处理时间回拨
|
||||
if sec < g.lastSec {
|
||||
// 计算需要等待的时间
|
||||
sleepDuration := time.Duration(g.lastSec-sec) * time.Second
|
||||
// 添加1毫秒缓冲,确保时间确实已过
|
||||
sleepDuration += time.Millisecond
|
||||
// 等待时间追上
|
||||
time.Sleep(sleepDuration)
|
||||
|
||||
// 重新获取时间戳
|
||||
now = time.Now()
|
||||
sec = uint32(now.Sub(g.Epoch).Seconds())
|
||||
|
||||
// 再次检查,防止极端情况
|
||||
if sec < g.lastSec {
|
||||
panic(errors.New("clock moved backwards beyond recovery"))
|
||||
}
|
||||
}
|
||||
|
||||
// 处理同一秒内的序列号
|
||||
if sec == g.lastSec {
|
||||
g.sequence++
|
||||
// 序列号溢出(8位最大255)
|
||||
if g.sequence > 255 { // 0-255是有效范围
|
||||
// 等待到下一秒
|
||||
sleepDuration := time.Second - time.Duration(now.Nanosecond())*time.Nanosecond + time.Microsecond
|
||||
time.Sleep(sleepDuration)
|
||||
|
||||
now = time.Now()
|
||||
sec = uint32(now.Sub(g.Epoch).Seconds())
|
||||
g.sequence = 0
|
||||
}
|
||||
} else {
|
||||
// 新的一秒,重置序列号
|
||||
g.sequence = 0
|
||||
}
|
||||
|
||||
// 更新上次时间戳
|
||||
g.lastSec = sec
|
||||
|
||||
// 组装ID (32位):
|
||||
// [28位秒级时间戳][5位节点ID][8位序列号]
|
||||
var id uint32
|
||||
id |= (sec << 13) // 左移13位(5+8)放置秒级时间戳
|
||||
id |= (uint32(g.nodeID) << 8) // 左移8位放置节点ID
|
||||
id |= uint32(g.sequence) // 放置序列号
|
||||
|
||||
return id
|
||||
}
|
||||
|
||||
// Parse extracts timestamp, node ID and sequence from a snowflake
|
||||
func (g *Generator) Parse(id uint32) (t time.Time, nodeID uint8, sequence uint8) {
|
||||
// 提取各部分信息
|
||||
sec := id >> 13
|
||||
nodeID = uint8((id >> 8) & 0x1F) // 5位掩码(0x1F = 31)
|
||||
sequence = uint8(id & 0xFF) // 8位掩码(0xFF = 255)
|
||||
|
||||
// 计算实际时间
|
||||
totalNanos := g.Epoch.UnixNano() + int64(sec)*int64(time.Second)
|
||||
t = time.Unix(0, totalNanos).UTC()
|
||||
return
|
||||
}
|
||||
|
||||
// GetNodeID returns the current node ID
|
||||
func (g *Generator) GetNodeID() uint8 {
|
||||
return g.nodeID
|
||||
}
|
||||
|
||||
// GetLastTimestamp returns the last timestamp used (for testing/debugging)
|
||||
func (g *Generator) GetLastTimestamp() uint32 {
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
return g.lastSec
|
||||
}
|
||||
|
||||
// MaxAge returns the maximum age (in seconds) that this generator can handle before overflow
|
||||
func (g *Generator) MaxAge() uint32 {
|
||||
return (1 << 28) - 1 // 268435455秒,约8.5年
|
||||
}
|
||||
|
||||
// MaxSequencePerSecond returns the maximum number of sequences per second
|
||||
func (g *Generator) MaxSequencePerSecond() uint8 {
|
||||
return 255 // 2^8 - 1
|
||||
}
|
||||
Reference in New Issue
Block a user