Golang 雪花算法

雪花算法(Snowflake Algorithm)是一种用于生成全局唯一 ID 的算法,特别适用于分布式系统。它的设计目标是生成趋势递增、高性能、可扩展的唯一 ID。让我为您提供一个基于 Go 语言的雪花算法示例代码。

首先,我们需要定义一些常量,包括时间戳的位数、机器 ID 的位数和序列号的位数。这些常量将在后面的代码中使用到。以下是定义常量的代码示例:

const (
    timestampBits = 41 // 时间戳位数
    machineIDBits = 10 // 机器 ID 位数
    sequenceBits  = 12 // 序列号位数

    maxMachineID   = -1 ^ (-1 << machineIDBits) // 最大机器 ID
    maxSequenceNum = -1 ^ (-1 << sequenceBits)  // 最大序列号
)

 接下来,我们定义一个结构体 Snowflake,用于存储雪花算法生成 ID 所需的各个参数:

type Snowflake struct {
    timestamp   int64 // 时间戳
    machineID   int64 // 机器 ID
    sequenceNum int64 // 序列号
}

 然后,我们编写一个初始化方法,用来设置结构体中的初始值。时间戳字段可以使用当前时间戳,机器 ID 可根据实际需求设置,序列号初始值设为 0:

func NewSnowflake(machineID int64) *Snowflake {
    if machineID < 0 || machineID > maxMachineID {
        panic("Invalid machine ID")
    }
    return &Snowflake{
        timestamp:   time.Now().UnixNano() / 1e6,
        machineID:   machineID,
        sequenceNum: 0,
    }
}

 最后,我们实现一个生成 ID 的方法,根据雪花算法的规则生成唯一 ID。具体实现过程包括获取当前时间戳、判断是否为同一毫秒、更新序列号等:

func (s *Snowflake) GenerateID() int64 {
    currentTimestamp := time.Now().UnixNano() / 1e6
    if currentTimestamp == s.timestamp {
        s.sequenceNum = (s.sequenceNum + 1) & maxSequenceNum
        if s.sequenceNum == 0 {
            currentTimestamp = s.waitNextMillis()
        }
    } else {
        s.sequenceNum = 0
    }
    s.timestamp = currentTimestamp

    id := (currentTimestamp << (machineIDBits + sequenceBits)) | (s.machineID << sequenceBits) | s.sequenceNum
    return id
}

func (s *Snowflake) waitNextMillis() int64 {
    currentTimestamp := time.Now().UnixNano() / 1e6
    for currentTimestamp <= s.timestamp {
        currentTimestamp = time.Now().UnixNano() / 1e6
    }
    return currentTimestamp
}

 您可以根据实际情况设置机器 ID,然后生成一些唯一 ID 并输出。以下是完整示例代码:

package main

import (
    "fmt"
    "time"
)

func main() {
    machineID := 1 // 根据实际情况设置机器 ID
    sf := NewSnowflake(int64(machineID))

    // 生成10个唯一 ID 并输出
    for i := 0; i < 10; i++ {
        id := sf.GenerateID()
        fmt.Println(id)
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
雪花算法是一种分布式唯一ID生成算法,它可以保证在分布式环境下生成唯一的ID。在Golang中,我们可以使用以下代码实现雪花算法: ```go package main import ( "errors" "fmt" "sync" "time" ) const ( // StartTime 是雪花算法开始时间戳,用于减小生成的ID长度 StartTime = 1577808000000 // 2020-01-01 00:00:00的时间戳,单位毫秒 // MachineIDBits 机器ID的位数 MachineIDBits = 10 // SequenceBits 序列号的位数 SequenceBits = 12 // MachineIDShift 机器ID的移位长度 MachineIDShift = SequenceBits // TimestampShift 时间戳的移位长度 TimestampShift = SequenceBits + MachineIDBits // MaxMachineID 最大机器ID MaxMachineID = -1 ^ (-1 << MachineIDBits) // MaxSequence 最大序列号 MaxSequence = -1 ^ (-1 << SequenceBits) ) // Snowflake 是雪花算法生成的唯一ID结构体 type Snowflake struct { machineID int64 // 机器ID sequence int64 // 序列号 lastStamp int64 // 上次生成ID的时间戳 idLock sync.Mutex } // NewSnowflake 创建一个新的雪花算法实例 func NewSnowflake(machineID int64) (*Snowflake, error) { if machineID < 0 || machineID > MaxMachineID { return nil, errors.New("machine ID out of range") } return &Snowflake{ machineID: machineID, }, nil } // Generate 生成一个新的唯一ID func (s *Snowflake) Generate() int64 { s.idLock.Lock() defer s.idLock.Unlock() // 获取当前时间戳 now := time.Now().UnixNano() / 1e6 // 如果当前时间小于上次生成ID的时间戳,说明系统时间被调整过,此时应该返回错误 if now < s.lastStamp { panic(fmt.Sprintf("time is moving backwards, refusing to generate id for %d milliseconds", s.lastStamp-now)) } // 如果当前时间与上次生成ID的时间戳相同,说明在同一毫秒内生成了多次ID,此时应将序列号+1 if now == s.lastStamp { s.sequence = (s.sequence + 1) & MaxSequence if s.sequence == 0 { // 序列号已经达到最大值,等待下一毫秒 for now <= s.lastStamp { now = time.Now().UnixNano() / 1e6 } } } else { // 当前时间与上次生成ID的时间戳不同,说明已经进入下一毫秒,序列号重置为0 s.sequence = 0 } // 保存当前时间戳,用于下一次生成ID时使用 s.lastStamp = now // 生成ID id := (now-StartTime)<<TimestampShift | (s.machineID << MachineIDShift) | s.sequence return id } func main() { // 创建一个新的雪花算法实例,机器ID为1 sf, err := NewSnowflake(1) if err != nil { panic(err) } // 生成10个唯一ID for i := 0; i < 10; i++ { id := sf.Generate() fmt.Println(id) } } ``` 在上面的代码中,我们首先定义了一些常量,包括开始时间、机器ID的位数、序列号的位数等。然后,我们定义了一个Snowflake结构体,用于保存生成ID时需要用到的一些参数,如机器ID、序列号、上次生成ID的时间戳等。接着,我们定义了NewSnowflake函数,用于创建一个新的雪花算法实例,并检查机器ID是否超出范围。最后,我们定义了Generate函数,用于生成一个新的唯一ID。在Generate函数中,我们首先获取当前时间戳,然后判断当前时间是否小于上次生成ID的时间戳,如果是,则说明系统时间被调整过,此时应该返回错误;如果当前时间与上次生成ID的时间戳相同,则说明在同一毫秒内生成了多次ID,此时应将序列号+1;如果当前时间与上次生成ID的时间戳不同,则说明已经进入下一毫秒,序列号重置为0。最后,我们将当前时间戳、机器ID、序列号组合成一个64位的唯一ID返回。 在main函数中,我们创建了一个新的雪花算法实例,并调用Generate函数生成了10个唯一ID。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值