go小项目-实现雪花算法

雪花算法(Snowflake Algorithm)是Twitter开源的一种分布式ID生成算法,它可以生成全局唯一且有序的64位ID。


一、雪花算法的结构

雪花算法生成的64位ID由以下部分组成:

  1. 符号位(1位) :固定为0,表示正数。
  2. 时间戳(41位) :表示从某个起始时间(如2025年1月1日)到当前时间的毫秒数。
  3. 机器ID(10位) :表示生成ID的机器或节点,支持最多1024个节点。
  4. 序列号(12位) :表示同一毫秒内生成的ID序号,支持每毫秒生成4096个ID。

二、Go语言实现雪花算法

go 复制代码
package main 
 
import (
	"errors"
	"fmt"
	"sync"
	"time"
)
 
// Snowflake 结构体 
type Snowflake struct {
	mu            sync.Mutex // 互斥锁,保证并发安全 
	startTime     int64      // 起始时间(毫秒)
	machineID     int64      // 机器ID 
	sequence      int64      // 序列号 
	lastTimestamp int64      // 上一次生成ID的时间戳 
}
 
// 常量 
const (
	machineIDBits  = 10 // 机器ID占用的位数 
	sequenceBits   = 12 // 序列号占用的位数 
	machineIDShift = sequenceBits // 机器ID左移位数 
	timestampShift = machineIDBits + sequenceBits // 时间戳左移位数 
	maxMachineID   = -1 ^ (-1 << machineIDBits) // 最大机器ID 
	maxSequence    = -1 ^ (-1 << sequenceBits) // 最大序列号 
)
 
// NewSnowflake 初始化雪花算法 
func NewSnowflake(machineID int64) (*Snowflake, error) {
	if machineID < 0 || machineID > maxMachineID {
		return nil, errors.New("machine ID out of range")
	}
	return &Snowflake{
		startTime:     time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC).UnixNano() / 1e6,
		machineID:     machineID,
		sequence:      0,
		lastTimestamp: -1,
	}, nil 
}
 
// NextID 生成下一个ID 
func (s *Snowflake) NextID() int64 {
	s.mu.Lock()
	defer s.mu.Unlock()
 
	// 获取当前时间戳 
	currentTimestamp := time.Now().UnixNano() / 1e6 
 
	// 如果当前时间小于上一次生成ID的时间,说明时钟回拨 
	if currentTimestamp < s.lastTimestamp {
		panic("clock moved backwards")
	}
 
	// 如果是同一毫秒内生成的ID 
	if currentTimestamp == s.lastTimestamp {
		s.sequence = (s.sequence + 1) & maxSequence 
		if s.sequence == 0 { // 如果序列号超出范围,等待下一毫秒 
			for currentTimestamp <= s.lastTimestamp {
				currentTimestamp = time.Now().UnixNano() / 1e6 
			}
		}
	} else {
		s.sequence = 0 
	}
 
	// 更新上一次生成ID的时间戳 
	s.lastTimestamp = currentTimestamp 
 
	// 生成ID 
	id := (currentTimestamp-s.startTime)<<timestampShift |
		(s.machineID << machineIDShift) |
		s.sequence 
	return id 
}
 
func main() {
	// 初始化雪花算法,机器ID为1 
	snowflake, err := NewSnowflake(1)
	if err != nil {
		panic(err)
	}
 
	// 生成10个ID 
	for i := 0; i < 10; i++ {
		id := snowflake.NextID()
		fmt.Println(id)
	}
}

三、代码解析

  1. Snowflake结构体

    • 包含生成ID所需的所有字段,如机器ID、序列号、上一次生成ID的时间戳等。
    • 使用sync.Mutex保证并发安全。
  2. 常量定义

    • 定义了机器ID、序列号的位数以及最大取值范围。
  3. NewSnowflake函数

    • 初始化雪花算法,检查机器ID是否在合法范围内。
  4. NextID方法

    • 生成下一个ID。
    • 处理时钟回拨问题。
    • 如果同一毫秒内生成的ID超出序列号范围,则等待下一毫秒。
  5. 主函数

    • 初始化雪花算法并生成10个ID。

四、运行结果

运行上述代码,会输出10个全局唯一且有序的64位ID,例如:

复制代码
129383475712 
129383475713 
129383475714 
129383475715 
129383475716 
129383475717 
129383475718 
129383475719 
129383475720 
129383475721 

五、注意事项

  1. 时钟回拨问题

    • 如果系统时间被回拨,可能会导致ID重复。代码中通过panic处理了这种情况,实际应用中可以根据需求选择更合适的处理方式(如等待或抛出异常)。
  2. 机器ID分配

    • 机器ID必须在0到1023之间,且每个节点必须分配唯一的ID。
  3. 性能优化

    • 雪花算法性能非常高,适合高并发场景。如果性能要求更高,可以进一步优化时间戳的获取方式。

通过Go语言实现雪花算法,可以轻松生成全局唯一且有序的ID。该算法简单高效,适合分布式系统中的ID生成需求。

相关推荐
程序员爱钓鱼4 小时前
Go语言实战案例 — 工具开发篇:实现一个图片批量压缩工具
后端·google·go
郭京京15 小时前
goweb内置的 net/http 包
后端·go
dylan_QAQ15 小时前
Java转Go全过程06-工程管理
java·后端·go
lypzcgf17 小时前
Coze源码分析-资源库-删除插件-后端源码-错误处理与总结
人工智能·后端·go·coze·coze源码分析·ai应用平台·agent平台
lypzcgf19 小时前
Coze源码分析-资源库-删除插件-后端源码-应用和领域服务层
后端·go·coze·coze插件·coze源码分析·智能体平台·ai应用平台
程序员爱钓鱼20 小时前
Go语言实战案例 — 工具开发篇:编写高可用日志收集脚本
后端·mongodb·go
今天头发还在吗1 天前
【Go】:mac 环境下GoFrame安装开发工具 gf-cli——gf_darwin_arm64
macos·golang·go·gf-cli
程序员爱钓鱼1 天前
Go语言实战案例-开发一个Markdown转HTML工具
前端·后端·go
一朵筋斗云2 天前
golang底层原理剖析
go
学历真的很重要2 天前
Claude Code Windows 原生版安装指南
人工智能·windows·后端·语言模型·面试·go