使用snowflake算法生成唯一id

Go语言中,可以使用snowflake算法生成唯一id。Snowflake算法是Twitter公司开源的一种分布式ID生成算法,它可以在分布式系统中生成唯一的ID,保证ID的全局唯一性,而且生成的ID是按照时间递增的。

以下是使用Go语言实现Snowflake算法生成唯一id的示例代码,在线运行

package main

import (
    "fmt"
    "time"
)

const (
    workerBits uint8 = 10
    seqBits    uint8 = 12

    maxWorkerNum int64 = -1 ^ (-1 << workerBits)
    maxSeqNum    int64 = -1 ^ (-1 << seqBits)

    timeShift   uint8 = workerBits + seqBits
    workerShift uint8 = seqBits
)

type snowflake struct {
    lastTimestamp int64
    workerId      int64
    sequence      int64
}

func newSnowflake(workerId int64) *snowflake {
    if workerId < 0 || workerId > maxWorkerNum {
        panic("workerId out of range")
    }
    return &snowflake{
        lastTimestamp: 0,
        workerId:      workerId,
        sequence:      0,
    }
}

func (sf *snowflake) NextId() int64 {
    timestamp := time.Now().UnixNano() / 1000000

    if timestamp < sf.lastTimestamp {
        panic("clock is moving backwards")
    }

    if timestamp == sf.lastTimestamp {
        sf.sequence = (sf.sequence + 1) & maxSeqNum
        if sf.sequence == 0 {
            for timestamp <= sf.lastTimestamp {
                timestamp = time.Now().UnixNano() / 1000000
            }
        }
    } else {
        sf.sequence = 0
    }

    sf.lastTimestamp = timestamp

    return (timestamp << timeShift) | (sf.workerId << workerShift) | sf.sequence
}

func main() {
    sf := newSnowflake(1)
    fmt.Println(sf.NextId())
}

在上述代码中,我们定义了一个snowflake结构体,其中包含了上一次生成的时间戳、workerId和sequence三个属性。在newSnowflake函数中,我们检查传入的workerId是否在合理范围内,然后初始化snowflake结构体的属性。在NextId函数中,我们首先获取当前时间戳,如果当前时间戳小于上一次生成的时间戳,说明时钟发生了回拨,此时需要抛出异常。如果当前时间戳等于上一次生成的时间戳,说明在同一毫秒内生成了多个ID,此时需要自增sequence,如果sequence达到了最大值,则需要等到下一个毫秒。如果当前时间戳大于上一次生成的时间戳,说明进入了下一个毫秒,此时需要将sequence重置为0,并更新lastTimestamp。最后,根据时间戳、workerId和sequence生成唯一的ID。

在本示例中,我们设置workerId=1生成了一个唯一的ID,你可以根据实际情况来使用不同的workerId。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!