golang分布式生成超短唯一非连续URL友好ID插件库shortid的使用

Golang分布式生成超短唯一非连续URL友好ID插件库shortid的使用

shortid是一个用于生成短小、完全唯一、非连续且默认URL友好的ID的Go语言库,每秒可生成数十万个ID,并保证在2050年前不会出现重复。

快速开始

最简单的使用方式:

fmt.Printf(shortid.Generate())
fmt.Printf(shortid.Generate())

推荐的方式是为特定worker初始化并重用生成器:

// 创建新的生成器实例
// 参数:worker编号(0-31),字母表,随机种子
sid, err := shortid.New(1, shortid.DefaultABC, 2342)

// 使用方式1:直接使用生成器实例
fmt.Printf(sid.Generate())
fmt.Printf(sid.Generate())

// 使用方式2:设置为默认生成器
shortid.SetDefault(sid)
// 然后使用全局函数生成
fmt.Printf(shortid.Generate())
fmt.Printf(shortid.Generate())

ID长度特性

  • 标准ID长度为9个字符(当以每秒1个ID的速度生成时)
  • 偶尔会达到11个字符(每秒数千个ID时)
  • 极少数情况下会更长(在持续高并发生成时)

生命周期保证

该库保证:

  • 34年内不会产生重复ID(2016-2050)
  • 支持最多32个worker同时生成唯一序列
  • 要求应用重启间隔大于1毫秒

完整示例

package main

import (
	"fmt"
	"github.com/teris-io/shortid"
)

func main() {
	// 初始化生成器
	sid, err := shortid.New(1, shortid.DefaultABC, 2342)
	if err != nil {
		panic(err)
	}

	// 生成10个ID
	for i := 0; i < 10; i++ {
		id := sid.Generate()
		fmt.Printf("Generated ID: %s\n", id)
	}

	// 设置为默认生成器
	shortid.SetDefault(sid)

	// 使用全局函数生成
	for i := 0; i < 5; i++ {
		id := shortid.Generate()
		fmt.Printf("Default generated ID: %s\n", id)
	}
}

实现特点

  1. 并发安全
  2. 不需要年度版本/epoch重置
  3. 在1ms速率下ID大小稳定
  4. 保证无冲突
  5. 支持32个worker(原node.js版支持16个)

算法细节

每个ID包含三部分信息:

  1. 从epoch开始的毫秒数(前8个字符,epoch: 2016/1/1)
  2. worker ID(第9个字符)
  3. 毫秒内的运行计数器(仅在需要时,占用剩余字符)

随机性:

  • worker和毫秒数据:1/2随机性
  • 计数器:无随机性

许可证

Copyright (c) 2016. Oleg Sklyar and teris.io. MIT license applies. All rights reserved.

更多关于golang分布式生成超短唯一非连续URL友好ID插件库shortid的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang分布式生成超短唯一非连续URL友好ID插件库shortid的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang分布式生成超短唯一非连续URL友好ID插件库shortid使用指南

shortid是一个用于生成分布式环境下超短、唯一、非连续且URL友好的ID的Go语言库。它特别适合需要生成短链接ID、订单号等场景。

安装

go get github.com/teris-io/shortid

基本用法

1. 生成ID

package main

import (
	"fmt"
	"github.com/teris-io/shortid"
)

func main() {
	// 生成一个ID
	id, err := shortid.Generate()
	if err != nil {
		panic(err)
	}
	fmt.Println("Generated ID:", id) // 输出类似: "g6XxXxXx"
}

2. 自定义配置

func customConfig() {
	// 自定义配置
	sid, err := shortid.New(1, shortid.DefaultABC, 2342)
	if err != nil {
		panic(err)
	}

	// 使用自定义配置生成ID
	id := sid.MustGenerate()
	fmt.Println("Custom ID:", id)
}

高级特性

1. 分布式支持

shortid支持分布式环境,通过为每个worker设置不同的worker编号来避免冲突:

func distributedUsage() {
	// worker编号从0开始,集群中每个实例应有唯一编号
	worker := 2 // 假设这是第3个worker
	
	sid, err := shortid.New(worker, shortid.DefaultABC, 2342)
	if err != nil {
		panic(err)
	}

	for i := 0; i < 5; i++ {
		fmt.Println("Distributed ID:", sid.MustGenerate())
	}
}

2. 自定义字符集

func customAlphabet() {
	// 自定义字符集(仅包含数字和大写字母)
	customABC := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	
	sid, err := shortid.New(1, customABC, 2342)
	if err != nil {
		panic(err)
	}

	fmt.Println("Custom alphabet ID:", sid.MustGenerate())
}

3. 设置随机种子

func withSeed() {
	// 设置随机种子以确保可重现结果(仅用于测试)
	sid, err := shortid.New(1, shortid.DefaultABC, 1234) // 固定seed
	if err != nil {
		panic(err)
	}

	// 每次运行都会生成相同的ID序列
	fmt.Println("ID with fixed seed 1:", sid.MustGenerate())
	fmt.Println("ID with fixed seed 2:", sid.MustGenerate())
}

性能考虑

shortid设计为高性能ID生成器,但如果你在极高并发环境下使用,可以考虑以下优化:

func concurrentUsage() {
	sid := shortid.MustNew(1, shortid.DefaultABC, 2342)
	
	// 使用channel批量生成ID
	ids := make(chan string, 100)
	go func() {
		for i := 0; i < 100; i++ {
			ids <- sid.MustGenerate()
		}
		close(ids)
	}()

	for id := range ids {
		fmt.Println(id)
	}
}

实际应用示例

短链接服务

package main

import (
	"fmt"
	"net/http"
	"github.com/teris-io/shortid"
)

var sid = shortid.MustNew(1, shortid.DefaultABC, 2342)

func main() {
	urlStore := make(map[string]string)
	
	http.HandleFunc("/shorten", func(w http.ResponseWriter, r *http.Request) {
		longURL := r.URL.Query().Get("url")
		if longURL == "" {
			http.Error(w, "URL parameter is required", http.StatusBadRequest)
			return
		}
		
		shortID := sid.MustGenerate()
		urlStore[shortID] = longURL
		
		fmt.Fprintf(w, "Short URL: http://localhost:8080/%s", shortID)
	})
	
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		shortID := r.URL.Path[1:]
		if longURL, ok := urlStore[shortID]; ok {
			http.Redirect(w, r, longURL, http.StatusFound)
		} else {
			http.NotFound(w, r)
		}
	})
	
	fmt.Println("Server started at :8080")
	http.ListenAndServe(":8080", nil)
}

注意事项

  1. 唯一性保证:确保在分布式环境中每个worker有唯一的编号
  2. 字符集选择:默认字符集是URL友好的,修改时需确保仍符合URL规范
  3. ID长度:生成的ID长度会随着生成数量的增加而自动增长
  4. 安全性:生成的ID不是加密安全的,不应用作安全令牌

shortid是一个简单高效的解决方案,适合需要短ID的大多数场景。对于更高要求的环境,也可以考虑其他方案如ULID或UUID。

回到顶部