一、雪花算法介绍
1. 由来
雪花算法英文名为SnowFlake,故为雪花。最早是 Twitter 公司在其内部用于分布式环境下生成唯一 ID。
2.作用:
雪花算法可以在分布式环境下生成全局唯一的int64类型的id。
3. 原理:
- 首先雪花算法由64位构成。
- 第一位永远为0。
- 后41位为unix毫秒。所以 2^41/(1000*3600*24*364) ~= 69.73,能保存69年左右,当然毫秒需要减去一个初始值,可以是业务运行开始时的毫秒数,这样算法才能用69年,超过69年就会发生id重复。
- 后10位分别为机器id和服务id,它们的范围都为0~31
- 最后10位为去重序列号,如果两次分配id在一个毫秒内,就用这个序列号来区分。也就是说雪花算法在一个实例上一毫秒可以产生4096个id。
二、实现
const (
machineBits = int64(5) //机器id位数
serviceBits = int64(5) //服务id位数
sequenceBits = int64(12) //序列id位数
maxMachineID = int64(-1) ^ (int64(-1) << machineBits) //最大机器id
maxServiceID = int64(-1) ^ (int64(-1) << serviceBits) //最大服务id
maxSequenceID = int64(-1) ^ (int64(-1) << sequenceBits) //最大序列id
timeLeft = uint8(22) //时间id向左移位的量
machineLeft = uint8(17) //机器id向左移位的量
serviceLeft = uint8(12) //服务id向左移位的量
twepoch = int64(1667972427000) //初始毫秒,时间是: Wed Nov 9 13:40:27 CST 2022
)
2.代码
type Worker struct {
sync.Mutex
lastStamp int64
machineID int64 //机器id,0~31
serviceID int64 //服务id,0~31
sequenceID int64
}
func NewWorker(machineID, serviceID int64) *Worker {
return &Worker{
lastStamp: 0,
machineID: machineID,
serviceID: serviceID,
sequenceID: 0,
}
}
func (w *Worker) GetID() int64 {
//多线程互斥
w.Lock()
defer w.Unlock()
mill := time.Now().UnixMilli()
if mill == w.lastStamp {
w.sequenceID = (w.sequenceID + 1) & maxSequenceID
//当一个毫秒内分配的id数>4096个时,只能等待到下一毫秒去分配。
if w.sequenceID == 0 {
for mill > w.lastStamp {
mill = time.Now().UnixMilli()
}
}
} else {
w.sequenceID = 0
}
w.lastStamp = mill
//fmt.Println(w.lastStamp - twepoch)
//fmt.Println((w.lastStamp - twepoch) << timeLeft)
//fmt.Printf("%bn", (w.lastStamp-twepoch)<<timeLeft)
id := (w.lastStamp-twepoch)<<timeLeft | w.machineID<<machineLeft | w.serviceID<<serviceLeft | w.sequenceID
return id
}
三、测试
var work = NewWorker(30, 30)
func main() {
var wg sync.WaitGroup
count := 10000
ch := make(chan int64, count)
wg.Add(count)
defer close(ch)
//并发 count个goroutine 进行 snowFlake ID 生成
for i := 0; i < count; i++ {
go func() {
defer wg.Done()
id := work.GetID()
ch <- id
}()
}
wg.Wait()
m := make(map[int64]int)
for i := 0; i < count; i++ {
id := <-ch
// 如果 map 中存在为 id 的 key, 说明生成的 snowflake ID 有重复
_, ok := m[id]
if ok {
fmt.Printf("repeat id %dn", id)
return
}
// 将 id 作为 key 存入 map
m[id] = i
}
// 成功生成 snowflake ID
fmt.Println("All", len(m), "snowflake ID Get successed!")
}
结果:
最详细的雪花算法讲解,包教包会(go版本)_51CTO博客_雪花算法解析
雪花算法(SnowFlake)_文丑颜不良啊的博客-CSDN博客_雪花算法
原文地址:https://blog.csdn.net/qq_42170897/article/details/127768047
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_27960.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。