golang高效生成带元数据的可排序唯一ID插件库sno的使用
Golang高效生成带元数据的可排序唯一ID插件库sno的使用
简介
sno是一个基于Snowflake设计的分布式系统唯一ID生成库,旨在对机器和人类友好、紧凑、多功能且快速。
特性
- 紧凑 - 二进制表示仅10字节,编码为16个字符
- 可排序 - 支持按时间排序
- 带时间戳 - 4毫秒分辨率,时间范围2010-2079年
- 带元数据字节 - 可嵌入任意数据
- 高性能 - 并发安全,无等待
- 高吞吐 - 每秒可生成≥16,384,000个ID
安装
go get -u github.com/muyo/sno
基本使用
使用默认生成器生成ID非常简单:
id := sno.New(0) // 0是元数据字节
完整示例
package main
import (
"fmt"
"github.com/muyo/sno"
)
const (
PersonType = iota
OtherType
)
type Person struct {
ID sno.ID
Name string
}
func main() {
// 使用默认生成器
id1 := sno.New(PersonType)
fmt.Println("Default generator ID:", id1)
// 创建自定义生成器
generator, _ := sno.NewGenerator(&sno.GeneratorSnapshot{
Partition: sno.Partition{'A', 10},
}, nil)
// 使用自定义生成器
id2 := generator.New(OtherType)
fmt.Println("Custom generator ID:", id2)
// 创建带元数据的Person
person := Person{
ID: sno.New(PersonType),
Name: "张三",
}
fmt.Printf("Person: %+v\n", person)
}
生成器配置
可以创建自定义生成器并配置分区:
generator, err := sno.NewGenerator(&sno.GeneratorSnapshot{
Partition: sno.Partition{'P', 0}, // 2字节分区
SequenceMin: 0, // 序列号最小值
SequenceMax: 32767, // 序列号最大值
}, nil)
元数据字节
元数据字节可以用于存储类型信息等:
const (
UserType = 1
OrderType = 2
)
// 生成用户ID
userID := sno.New(UserType)
// 生成订单ID
orderID := sno.New(OrderType)
性能
sno在性能上表现优异,生成每个ID仅需约8.8纳秒。
与其他库对比
名称 | 二进制大小 | 编码大小 | 可排序 | 随机性 | 元数据 | 性能(ns/ID) |
---|---|---|---|---|---|---|
sno | 10字节 | 16字符 | 是 | 否 | 是 | 8.8 |
UUID | 16字节 | 36字符 | 否 | 是 | 否 | ≥36.3 |
KSUID | 20字节 | 27字符 | 是 | 是 | 否 | 206.0 |
ULID | 16字节 | 26字符 | 是 | 是 | 否 | ≥50.3 |
Snowflake | 8字节 | ≤20字符 | 是 | 否 | 否 | 28.9 |
总结
sno是一个高效、紧凑且功能丰富的唯一ID生成库,特别适合需要嵌入元数据并按时间排序的场景。其简单的API和出色的性能使其成为许多Go项目的理想选择。
更多关于golang高效生成带元数据的可排序唯一ID插件库sno的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang高效生成带元数据的可排序唯一ID插件库sno的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用sno生成带元数据的可排序唯一ID
sno是一个高效的Go库,用于生成可排序的、包含元数据的唯一ID(类似Twitter的Snowflake ID)。下面我将详细介绍sno的使用方法。
sno的特点
- 可排序性:ID按时间顺序生成,便于数据库索引
- 包含元数据:可嵌入分区、节点等信息
- 高效:无锁设计,性能优异
- 紧凑:使用Base32编码,比UUID更短
安装
go get github.com/muyo/sno
基本使用
package main
import (
"fmt"
"github.com/muyo/sno"
)
func main() {
// 1. 创建一个生成器实例
// 参数:节点ID (0-31)
generator, err := sno.NewGenerator(1)
if err != nil {
panic(err)
}
// 2. 生成ID
id := generator.New()
fmt.Println("生成的ID:", id)
fmt.Println("字符串表示:", id.String())
fmt.Println("字节表示:", id.Bytes())
fmt.Println("时间戳部分:", id.Time())
fmt.Println("序列号部分:", id.Sequence())
}
带元数据的ID生成
sno允许在ID中嵌入1字节的元数据(0-255):
func main() {
generator, _ := sno.NewGenerator(1)
// 生成带元数据的ID
idWithMeta := generator.NewWithMeta(42) // 42是元数据
fmt.Println("带元数据的ID:", idWithMeta)
fmt.Println("解析出的元数据:", idWithMeta.Meta())
}
性能基准
sno的性能非常高,以下是一个简单的基准测试:
func BenchmarkGenerate(b *testing.B) {
generator, _ := sno.NewGenerator(1)
b.ResetTimer()
for i := 0; i < b.N; i++ {
generator.New()
}
}
/*
典型结果:
BenchmarkGenerate-8 10000000 120 ns/op
*/
实际应用示例
分布式系统中的应用
package main
import (
"fmt"
"github.com/muyo/sno"
)
const (
MetaUser = 1
MetaProduct = 2
MetaOrder = 3
)
var (
userGenerator *sno.Generator
productGenerator *sno.Generator
orderGenerator *sno.Generator
)
func init() {
var err error
userGenerator, err = sno.NewGenerator(1)
if err != nil {
panic(err)
}
productGenerator, err = sno.NewGenerator(2)
if err != nil {
panic(err)
}
orderGenerator, err = sno.NewGenerator(3)
// 可以设置不同的节点ID来区分不同的服务实例
}
func NewUserID() sno.ID {
return userGenerator.NewWithMeta(MetaUser)
}
func NewProductID() sno.ID {
return productGenerator.NewWithMeta(MetaProduct)
}
func NewOrderID() sno.ID {
return orderGenerator.NewWithMeta(MetaOrder)
}
func main() {
userID := NewUserID()
productID := NewProductID()
orderID := NewOrderID()
fmt.Printf("User ID: %s (meta: %d)\n", userID, userID.Meta())
fmt.Printf("Product ID: %s (meta: %d)\n", productID, productID.Meta())
fmt.Printf("Order ID: %s (meta: %d)\n", orderID, orderID.Meta())
}
数据库主键示例
package main
import (
"database/sql"
"fmt"
"github.com/muyo/sno"
_ "github.com/lib/pq"
)
type User struct {
ID sno.ID
Name string
Email string
}
func main() {
db, err := sql.Open("postgres", "user=postgres dbname=test sslmode=disable")
if err != nil {
panic(err)
}
defer db.Close()
generator, _ := sno.NewGenerator(1)
// 创建用户
user := User{
ID: generator.NewWithMeta(1), // 1表示用户类型
Name: "John Doe",
Email: "john@example.com",
}
_, err = db.Exec("INSERT INTO users (id, name, email) VALUES ($1, $2, $3)",
user.ID, user.Name, user.Email)
if err != nil {
panic(err)
}
// 查询用户
var fetchedUser User
err = db.QueryRow("SELECT id, name, email FROM users WHERE id = $1", user.ID).
Scan(&fetchedUser.ID, &fetchedUser.Name, &fetchedUser.Email)
if err != nil {
panic(err)
}
fmt.Printf("Fetched user: %+v\n", fetchedUser)
}
注意事项
- 节点ID范围是0-31,确保在分布式系统中每个节点有唯一ID
- 时间戳部分使用41位,大约可以使用69年
- 序列号12位,每毫秒可生成4096个ID
- 默认使用Base32编码,输出字符串长度为20个字符
sno是一个简单但功能强大的ID生成库,特别适合需要可排序ID和嵌入元数据的场景。它的性能优异,适合高并发环境使用。