guid.go

package nsqd

// the core algorithm here was borrowed from:
// Blake Mizerany's `noeqd` https://github.com/bmizerany/noeqd
// and indirectly:
// Twitter's `snowflake` https://github.com/twitter/snowflake

// only minor cleanup and changes to introduce a type, combine the concept
// of workerID + datacenterId into a single identifier, and modify the
// behavior when sequences rollover for our specific implementation needs

import (
    "encoding/hex"
    "errors"
    "time"
)

const (
    workerIDBits   = uint64(10)
    sequenceBits   = uint64(12)
    workerIDShift  = sequenceBits
    timestampShift = sequenceBits + workerIDBits
    sequenceMask   = int64(-1) ^ (int64(-1) << sequenceBits)

    // ( 2012-10-28 16:23:42 UTC ).UnixNano() >> 20
    twepoch = int64(1288834974288)
)

var ErrTimeBackwards = errors.New("time has gone backwards")
var ErrSequenceExpired = errors.New("sequence expired")
var ErrIDBackwards = errors.New("ID went backward")

type guid int64

type guidFactory struct {
    sequence      int64
    lastTimestamp int64
    lastID        guid
}

func (f *guidFactory) NewGUID(workerID int64) (guid, error) {
    // divide by 1048576, giving pseudo-milliseconds
    ts := time.Now().UnixNano() >> 20

    if ts < f.lastTimestamp {
        return 0, ErrTimeBackwards
    }

    if f.lastTimestamp == ts {
        f.sequence = (f.sequence + 1) & sequenceMask
        if f.sequence == 0 {
            return 0, ErrSequenceExpired
        }
    } else {
        f.sequence = 0
    }

    f.lastTimestamp = ts

    id := guid(((ts - twepoch) << timestampShift) |
        (workerID << workerIDShift) |
        f.sequence)

    if id <= f.lastID {
        return 0, ErrIDBackwards
    }

    f.lastID = id

    return id, nil
}

func (g guid) Hex() MessageID {
    var h MessageID
    var b [8]byte

    b[0] = byte(g >> 56)
    b[1] = byte(g >> 48)
    b[2] = byte(g >> 40)
    b[3] = byte(g >> 32)
    b[4] = byte(g >> 24)
    b[5] = byte(g >> 16)
    b[6] = byte(g >> 8)
    b[7] = byte(g)

    hex.Encode(h[:], b[:])
    return h
}

转载于:https://www.cnblogs.com/zhangboyu/p/7457316.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值