golang 分布式id生成器

在高并发场景中,通常需要像mysql中那样的自增主键一样的不会重复且自增的id生成

twitter的snowflake就是一种典型的解法,id数值长64位,是一个int64类型,被分为四个部分:

  • 最高位不使用
  • 41位表示收到请求的时间戳,单位为毫秒
  • 5位表示数据中心的id
  • 5位表示机器实例的id
  • 12位循环自增id,1111,1111,1111后归零

这样的机制可以保证一台机器在一毫秒内产生4096条消息,一秒总共409.6万条消息

数据中心id配合实例id一共有10位,每个数据中心可以部署32台实例,搭建32个数据中心,所以一共存在1024个实例

41位时间戳可以使用69年

 

1. github.com/bwmarrin/snowflake

github.com/bwmarrin/snowflake是一个轻量级的snowflake实现

首先需要引入依赖

go get github.com/bwmarrin/snowflake

 

这个库使用起来也非常简单

func main(){
node,err:=snowflak.NewNode(1)
if err!=nil{
println(err.Error())
os.Exit(1)
}
for i:=0;i<20;i++{
id:=node.Generate()
fmt.Printf( "int64 ID: %d\n" ,id)
fmt.Printf( "string ID: %s\n" ,id)
fmt.Printf( "base2 ID: %s\n" ,id.Base2())
fmt.Printf( "base64 ID: %s\n" ,id.Base64())
fmt.Printf( "ID time: %d\n" ,id.Time())
fmt.Printf( "ID node: %d\n" ,id.Node())
fmt.Printf( "ID step: %d\n" ,id.Step())
fmt.Println( "--------------------------------" )
}
}

 

这个库是一个单文件,其中提供了我们可以定制的参数

其中Epoch是起始时间、NodeBits是实例id的长度,默认10位、StepBits是自增id的长度,默认12位

 

2. github.com/sony/sonyflake

snoyflake侧重于多主机多实例的生命周期和性能,所以与snowflake使用了不同的位分配:

  • 比snowflake更长的生命周期,174年
  • 能运行在更多的实例上,216个
  • 生成id的速度比snowflake慢,10ms内最多生成28个

 

snoyflake在启动阶段需要配置参数,主要是一个Setting结构体

type Settings struct {
StartTime      time.Time              // 起始时间,默认2014-09-01 00:00:00 +0000 UTC
MachineID      func () (uint16, error) // 返回实例ID的函数,如果不定义此函外,默认用本机ip的低16位
CheckMachineID func (uint16) bool      // 验证实例ID/计算机ID的唯一性,返回true时才创建
}

 

我们需要自己实现这两个函数:

func getMachineID() (uint16, error) {
var machineID uint16 = 6
return machineID, nil
}
func checkMachineID(machineID uint16) bool {
existsMachines := []uint16{1, 2, 3, 4, 5}
for _, v := range existsMachines {
if v == machineID {
return false
}
}
return true
}

 

func main() {
t, _ := time.Parse( "2006-01-02" , "2021-01-01" )
settings := sonyflake.Settings{
StartTime:      t,
MachineID:      getMachineID,
CheckMachineID: checkMachineID,
}
sf := sonyflake.NewSonyflake(settings)
for i := 0; i < 10; i++ {
id, err := sf.NextID()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println(id)
}
}

 

posted @   aganippe  阅读(562)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示