
雪花算法
背景
雪花算法是 twitter 高并发环境下对唯一 ID 生成的需求。
结构
主要分为 4 个部分
- 一个 bit,无意义。
- 41 个 bit,表示时间戳。
- 10 个 bit,表示机房 id 和 机器 id。可任意拆分。
- 12 个 bit 表示某个机房在这一毫秒内生成的 id 的序列号。
实现
结构定义
// SnowFlake 雪花算法 id 生成器
type SnowFlake struct {
mutex *sync.Mutex
LastStamp int64 // 上次 id 的时间戳
WorkerID int64 // 节点 id
Sequence int64 // 当前毫秒已经生成的 id 序列号
}
基本常量
const (
_workerIDBits = uint64(10) // 机器 id 长度
_sequenceBits = uint64(12) // 序列号长度
)
const (
_maxSequence = int64(-1) ^ (int64(-1) << int64(_sequenceBits)) // 最大序列号
)
const (
_timeLeft = _workerIDBits + _sequenceBits // 时间戳偏移量
_workerLeft = _sequenceBits // 序列号偏移量
)
const (
_timeStamp = int64(1607616000000) // 常量时间戳 2020-12-11-00-00
)
生成 ID
func (s SnowFlake) getMilliSeconds() int64 {
return time.Now().UnixMilli()
}
// NextID 生成 id
func (s *SnowFlake) NextID() (uint64, error) {
s.mutex.Lock()
defer s.mutex.Unlock()
timeStamp := s.getMilliSeconds()
if timeStamp < s.LastStamp {
return 0, errors.New("")
} else if timeStamp == s.LastStamp {
s.Sequence = (s.Sequence + 1) & _maxSequence
// 若序列号溢出,则等待下一毫秒
if s.Sequence == 0 {
for timeStamp <= s.LastStamp {
timeStamp = s.getMilliSeconds()
}
}
} else {
s.Sequence = 0
}
s.LastStamp = timeStamp
id := ((timeStamp - _timeStamp) << int64(_timeLeft)) |
(s.WorkerID << int64(_workerLeft)) |
s.Sequence
return uint64(id), nil
}