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博客_雪花算法


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部