go实现雪花算法
一、雪花算法介绍
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。
二、实现
1.常量定义
const (machineBits = int64(5) //机器id位数serviceBits = int64(5) //服务id位数sequenceBits = int64(12) //序列id位数maxMachineID = int64(-1) ^ (int64(-1) << machineBits) //最大机器idmaxServiceID = int64(-1) ^ (int64(-1) << serviceBits) //最大服务idmaxSequenceID = int64(-1) ^ (int64(-1) << sequenceBits) //最大序列idtimeLeft = 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.MutexlastStamp int64machineID int64 //机器id,0~31serviceID int64 //服务id,0~31sequenceID 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("%b\n", (w.lastStamp-twepoch)<
三、测试
10000个协程同时请求id:
var work = NewWorker(30, 30)func main() {var wg sync.WaitGroupcount := 10000ch := 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 %d\n", id)return}// 将 id 作为 key 存入 mapm[id] = i}// 成功生成 snowflake IDfmt.Println("All", len(m), "snowflake ID Get successed!")
}
结果:
![]()
参考文献:
最详细的雪花算法讲解,包教包会(go版本)_51CTO博客_雪花算法解析
雪花算法(SnowFlake)_文丑颜不良啊的博客-CSDN博客_雪花算法
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
