|
@@ -1,40 +1,147 @@
|
|
package util
|
|
package util
|
|
|
|
|
|
import (
|
|
import (
|
|
|
|
+ "errors"
|
|
"fmt"
|
|
"fmt"
|
|
- "github.com/bwmarrin/snowflake"
|
|
|
|
"github.com/spf13/viper"
|
|
"github.com/spf13/viper"
|
|
|
|
+ "sync"
|
|
"time"
|
|
"time"
|
|
)
|
|
)
|
|
|
|
|
|
-var node *snowflake.Node
|
|
|
|
|
|
+type SnowFlakeIdWorker struct {
|
|
|
|
|
|
-func init() {
|
|
|
|
- tie := viper.GetString("time.time")
|
|
|
|
- if err := Init(tie, 1); err != nil {
|
|
|
|
- fmt.Println("Init() failed, err = ", err)
|
|
|
|
- return
|
|
|
|
|
|
+ // 开始时间戳
|
|
|
|
+ twepoch int64
|
|
|
|
+
|
|
|
|
+ // 机器ID所占的位数
|
|
|
|
+ workerIdBits int64
|
|
|
|
+
|
|
|
|
+ // 数据标识ID所占的位数
|
|
|
|
+ dataCenterIdBits int64
|
|
|
|
+
|
|
|
|
+ // 支持的最大机器ID
|
|
|
|
+ maxWorkerId int64
|
|
|
|
+
|
|
|
|
+ // 支持的最大机房 ID
|
|
|
|
+ maxDataCenterId int64
|
|
|
|
+
|
|
|
|
+ // 序列在ID中占的位数
|
|
|
|
+ sequenceBits int64
|
|
|
|
+
|
|
|
|
+ // 机器ID向左移位数
|
|
|
|
+ workerIdShift int64
|
|
|
|
+
|
|
|
|
+ // 机房ID向左移位数
|
|
|
|
+ dataCenterIdShift int64
|
|
|
|
+
|
|
|
|
+ // 时间截向左移位数
|
|
|
|
+ timestampLeftShift int64
|
|
|
|
+
|
|
|
|
+ // 生成序列的掩码最大值
|
|
|
|
+ sequenceMask int64
|
|
|
|
+
|
|
|
|
+ // 工作机器ID
|
|
|
|
+ workerId int64
|
|
|
|
+
|
|
|
|
+ // 机房ID
|
|
|
|
+ dataCenterId int64
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 毫秒内序列
|
|
|
|
+ */
|
|
|
|
+ sequence int64
|
|
|
|
+
|
|
|
|
+ // 上次生成ID的时间戳
|
|
|
|
+ lastTimestamp int64
|
|
|
|
+
|
|
|
|
+ // 锁
|
|
|
|
+ lock sync.Mutex
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (p *SnowFlakeIdWorker) init(dataCenterId int64, workerId int64) {
|
|
|
|
+ t, _ := time.Parse("2006-01-02", viper.GetString("time.time"))
|
|
|
|
+ // 开始时间戳;这里是2021-06-01
|
|
|
|
+ p.twepoch = t.Unix()
|
|
|
|
+ // 机器ID所占的位数
|
|
|
|
+ p.workerIdBits = 5
|
|
|
|
+ // 数据标识ID所占的位数
|
|
|
|
+ p.dataCenterIdBits = 5
|
|
|
|
+ // 支持的最大机器ID,最大是31
|
|
|
|
+ p.maxWorkerId = -1 ^ (-1 << p.workerIdBits)
|
|
|
|
+ // 支持的最大机房ID,最大是 31
|
|
|
|
+ p.maxDataCenterId = -1 ^ (-1 << p.dataCenterIdBits)
|
|
|
|
+ // 序列在ID中占的位数
|
|
|
|
+ p.sequenceBits = 12
|
|
|
|
+ // 机器ID向左移12位
|
|
|
|
+ p.workerIdShift = p.sequenceBits
|
|
|
|
+ // 机房ID向左移17位
|
|
|
|
+ p.dataCenterIdShift = p.sequenceBits + p.workerIdBits
|
|
|
|
+ // 时间截向左移22位
|
|
|
|
+ p.timestampLeftShift = p.sequenceBits + p.workerIdBits + p.dataCenterIdBits
|
|
|
|
+ // 生成序列的掩码最大值,最大为4095
|
|
|
|
+ p.sequenceMask = -1 ^ (-1 << p.sequenceBits)
|
|
|
|
+
|
|
|
|
+ if workerId > p.maxWorkerId || workerId < 0 {
|
|
|
|
+ panic(errors.New(fmt.Sprintf("Worker ID can't be greater than %d or less than 0", p.maxWorkerId)))
|
|
}
|
|
}
|
|
|
|
+ if dataCenterId > p.maxDataCenterId || dataCenterId < 0 {
|
|
|
|
+ panic(errors.New(fmt.Sprintf("DataCenter ID can't be greater than %d or less than 0", p.maxDataCenterId)))
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ p.workerId = workerId
|
|
|
|
+ p.dataCenterId = dataCenterId
|
|
|
|
+ // 毫秒内序列(0~4095)
|
|
|
|
+ p.sequence = 0
|
|
|
|
+ // 上次生成 ID 的时间戳
|
|
|
|
+ p.lastTimestamp = -1
|
|
}
|
|
}
|
|
|
|
|
|
-func Init(startTime string, machineID int64) (err error) {
|
|
|
|
- var st time.Time
|
|
|
|
- // 格式化 1月2号下午3时4分5秒 2006年
|
|
|
|
- st, err = time.Parse("2006-01-02", startTime)
|
|
|
|
- if err != nil {
|
|
|
|
- fmt.Println(err)
|
|
|
|
- return
|
|
|
|
|
|
+// 生成ID,注意此方法已经通过加锁来保证线程安全
|
|
|
|
+func (p *SnowFlakeIdWorker) nextId() int64 {
|
|
|
|
+ p.lock.Lock()
|
|
|
|
+ defer p.lock.Unlock()
|
|
|
|
+
|
|
|
|
+ timestamp := p.timeGen()
|
|
|
|
+ // 如果当前时间小于上一次 ID 生成的时间戳,说明发生时钟回拨,为保证ID不重复抛出异常。
|
|
|
|
+ if timestamp < p.lastTimestamp {
|
|
|
|
+ panic(errors.New(fmt.Sprintf("Clock moved backwards. Refusing to generate id for %d milliseconds", p.lastTimestamp-timestamp)))
|
|
}
|
|
}
|
|
|
|
|
|
- snowflake.Epoch = st.UnixNano() / 1e6
|
|
|
|
- node, err = snowflake.NewNode(machineID)
|
|
|
|
- if err != nil {
|
|
|
|
- fmt.Println(err)
|
|
|
|
- return
|
|
|
|
|
|
+ if p.lastTimestamp == timestamp {
|
|
|
|
+ // 同一时间生成的,则序号+1
|
|
|
|
+ p.sequence = (p.sequence + 1) & p.sequenceMask
|
|
|
|
+ // 毫秒内序列溢出:超过最大值
|
|
|
|
+ if p.sequence == 0 {
|
|
|
|
+ // 阻塞到下一个毫秒,获得新的时间戳
|
|
|
|
+ timestamp = p.tilNextMillis(p.lastTimestamp)
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ // 时间戳改变,序列重置
|
|
|
|
+ p.sequence = 0
|
|
}
|
|
}
|
|
- return
|
|
|
|
|
|
+ // 保存本次的时间戳
|
|
|
|
+ p.lastTimestamp = timestamp
|
|
|
|
+
|
|
|
|
+ // 移位并通过或运算拼到一起
|
|
|
|
+ return ((timestamp - p.twepoch) << p.timestampLeftShift) |
|
|
|
|
+ (p.dataCenterId << p.dataCenterIdShift) |
|
|
|
|
+ (p.workerId << p.workerIdShift) | p.sequence
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (p *SnowFlakeIdWorker) tilNextMillis(lastTimestamp int64) int64 {
|
|
|
|
+ timestamp := p.timeGen()
|
|
|
|
+ for timestamp <= lastTimestamp {
|
|
|
|
+ timestamp = p.timeGen()
|
|
|
|
+ }
|
|
|
|
+ return timestamp
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (p *SnowFlakeIdWorker) timeGen() int64 {
|
|
|
|
+ return time.Now().UnixNano() / 1e6
|
|
}
|
|
}
|
|
|
|
|
|
-func GenID() int64 {
|
|
|
|
- return node.Generate().Int64()
|
|
|
|
|
|
+func GetID() int64 {
|
|
|
|
+ idWorker := &SnowFlakeIdWorker{}
|
|
|
|
+ idWorker.init(0, 1)
|
|
|
|
+ return idWorker.nextId()
|
|
}
|
|
}
|