您的位置 首页 golang

golang雪花算法SnowFlake解决时间回拨问题

package mainimport (    "errors"    "fmt"    "sync"    "time")const (    workerBits uint8 = 10 // 每台机器(节点)的id位数 10位最大可以有2^10=1024个节点(0-1023)    numberBits uint8 = 22 // 表示每个集群下的每个节点,1秒内可生成的id序号的二进制位数 即每秒可生成 2^22-1=4194304个唯一id(0-4194303)    // 这里求最大值使用了位运算    workerMax   int64 = ^(-1 << workerBits)     // 节点ID的最大值,用于防止溢出    numberMax   int64 = ^(-1 << numberBits)     // 每个节点,1秒内可生成的id序号最大值    timeShift   uint8 = workerBits + numberBits // 时间戳向左的偏移量    workerShift uint8 = numberBits              // 节点id向左的偏移量    // 31位字节作为时间戳数值的话 大约68年就会用完    // 假如你2010年1月1日开始开发系统 如果不减去2010年1月1日的时间戳 那么白白浪费40年的时间戳啊!    // 这个一旦定义且开始生成ID后千万不要改了 不然可能会生成相同的ID    epoch int64 = 1589904000 //这个是我在写epoch这个变量时的时间戳(秒))// 定义一个woker工作节点所需要的基本参数type Worker struct {    mu        sync.Mutex     // 添加互斥锁 确保并发安全    timestamp int64          // 记录时间戳    workerId  int64          // 该节点的ID    number    int64          // 当前毫秒已经生成的id序列号(从0开始累加) 1秒内最多生成4194304个id    idMap     map[int64]bool //生成的所有不重复的id map,用于测试校验是否产生重复id,正式环境不需要    flag      bool           //用于测试时间回拨字段,正式环境不需要}// @desc 初始化一个节点// @auth liuguoqiang 2020-06-16// @param// @returnfunc NewWorker(workerId int64) (*Worker, error) {    // 要先检测workerId是否在上面定义的范围内    if workerId < 0 || workerId > workerMax {        return nil, errors.New("workId is invalidate")    }    return &Worker{        timestamp: 0,        workerId:  workerId,        number:    0,        idMap:     make(map[int64]bool),        flag:      false,    }, nil}// @desc 获取id// @auth liuguoqiang 2020-06-16// @param// @returnfunc (w *Worker) GetId() int64 {    //解决并发安全    w.mu.Lock()    defer w.mu.Unlock()    //获取生成时的时间戳    now := w.Now()    if now == w.timestamp {        w.number++        //这里要判断,当前工作节点是否在1秒内已经生成numberMax个id        if w.number > numberMax {            //如果当前工作节点在1秒内生成的id已经超过上限 需要等待1秒再继续生成            w.number = 0            for now <= w.timestamp {                now = w.Now()            }            w.timestamp = now        }    } else if now > w.timestamp {        //如果当前时间与工作节点上一次生成id的时间不一致 则需要重置工作节点生成id的序号        w.number = 0        //将机器上一次生成id的时间更新为当前时间        w.timestamp = now    } else {        for now < w.timestamp {            now = w.Now()        }        w.number++        //这里要判断,当前工作节点是否在1秒内已经生成numberMax个id        if w.number > numberMax {            //如果当前工作节点在1秒内生成的id已经超过上限 需要等待1秒再继续生成            w.number = 0            for now <= w.timestamp {                now = w.Now()            }            w.timestamp = now        }    }    //第一段 now - epoch 为该算法目前已经奔跑了秒    //如果在程序跑了一段时间修改了epoch这个值 可能会导致生成相同的id    id := int64((now-epoch)<<timeShift | (w.workerId << workerShift) | (w.number))    //检查是否有重复的id正式环境不需要    if _, ok := w.idMap[id]; ok {        fmt.Printf("重复id:%#v,%d,%d,%#v\n", id, w.number, w.timestamp, w.flag)    }    w.idMap[id] = true    return id}// @desc 获取当前时间// @auth liuguoqiang 2020-06-16// @param// @returnfunc (w *Worker) Now() int64 {    //模拟时间回拨10秒,正式环境不需要    if w.flag {        return time.Now().Unix() - 10    }    if w.number == numberMax/2 && !w.flag {        w.flag = true        return time.Now().Unix() - 10    }    return time.Now().Unix()}func main() {    // 生成节点实例    worker, err := NewWorker(1)    if err != nil {        fmt.Println(err)        return    }    count := 40000000    for i := 0; i < count; i++ {        _ = worker.GetId()    }    i := 0    for _, _ = range worker.idMap {        i++    }    fmt.Println("Id总数", count)    fmt.Println("不重复Id数量", i)}

文章来源:智云一二三科技

文章标题:golang雪花算法SnowFlake解决时间回拨问题

文章地址:https://www.zhihuclub.com/6887.shtml

关于作者: 智云科技

热门文章

发表评论

您的电子邮箱地址不会被公开。

2条评论

  1. Ngxuts Cephalexin Dosage – Cialis Jdodft Cialis 10 Mg Bestellen Afmuxb The details of how immunity works are fiendishly complex and still being unraveled. Kldcel – Cialis

  2. Tcvdbg Payne described pressure on her pituitary gland parathyroid gland pubic symphysis making it difcult for her to nd a comfortable position even when seated. – generic 5mg cialis best price cialis wholesale online Ihznpg I Poor diet and exercise has been linked to percent of cancers. Fqoayg Levaquin Medication Cheap Pharmacy – Cialis

网站地图