You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
|
|
|
package tools
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"sync"
|
|
|
|
|
|
"time"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
|
epoch = int64(1577808000000) // 设置起始时间(时间戳/毫秒):2020-01-01 00:00:00,有效期69年
|
|
|
|
|
|
timestampBits = uint(41) // 时间戳占用位数
|
|
|
|
|
|
datacenteridBits = uint(5) // 数据中心id所占位数
|
|
|
|
|
|
workeridBits = uint(5) // 机器id所占位数
|
|
|
|
|
|
sequenceBits = uint(12) // 序列所占的位数
|
|
|
|
|
|
timestampMax = int64(-1 ^ (-1 << timestampBits)) // 时间戳最大值
|
|
|
|
|
|
sequenceMask = int64(-1 ^ (-1 << sequenceBits)) // 支持的最大序列id数量
|
|
|
|
|
|
workeridShift = sequenceBits // 机器id左移位数
|
|
|
|
|
|
datacenteridShift = sequenceBits + workeridBits // 数据中心id左移位数
|
|
|
|
|
|
timestampShift = sequenceBits + workeridBits + datacenteridBits // 时间戳左移位数
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
type snowflake struct {
|
|
|
|
|
|
sync.Mutex
|
|
|
|
|
|
timestamp int64
|
|
|
|
|
|
workerid int64
|
|
|
|
|
|
datacenterid int64
|
|
|
|
|
|
sequence int64
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var s = &snowflake{
|
|
|
|
|
|
timestamp: 0,
|
|
|
|
|
|
datacenterid: 1,
|
|
|
|
|
|
workerid: 2,
|
|
|
|
|
|
sequence: 0,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func SnowflakeId() int64 {
|
|
|
|
|
|
return s.nextVal()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// nextVal 返回下一个Snowflake ID
|
|
|
|
|
|
func (s *snowflake) nextVal() int64 {
|
|
|
|
|
|
s.Lock()
|
|
|
|
|
|
now := time.Now().UnixNano() / 1000000 // 转毫秒
|
|
|
|
|
|
if s.timestamp == now {
|
|
|
|
|
|
// 当同一时间戳(精度:毫秒)下多次生成id会增加序列号
|
|
|
|
|
|
s.sequence = (s.sequence + 1) & sequenceMask
|
|
|
|
|
|
if s.sequence == 0 {
|
|
|
|
|
|
// 如果当前序列超出12bit长度,则需要等待下一毫秒
|
|
|
|
|
|
// 下一毫秒将使用sequence:0
|
|
|
|
|
|
for now <= s.timestamp {
|
|
|
|
|
|
now = time.Now().UnixNano() / 1000000
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 不同时间戳(精度:毫秒)下直接使用序列号:0
|
|
|
|
|
|
s.sequence = 0
|
|
|
|
|
|
}
|
|
|
|
|
|
t := now - epoch
|
|
|
|
|
|
if t > timestampMax {
|
|
|
|
|
|
s.Unlock()
|
|
|
|
|
|
return epoch
|
|
|
|
|
|
}
|
|
|
|
|
|
s.timestamp = now
|
|
|
|
|
|
r := (t)<<timestampShift | (s.datacenterid << datacenteridShift) | (s.workerid << workeridShift) | (s.sequence)
|
|
|
|
|
|
s.Unlock()
|
|
|
|
|
|
return r
|
|
|
|
|
|
}
|