You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何生成低碰撞高并发的10字符类zua-qysx-emr格式唯一随机序列ID?

符合要求的ID生成算法设计

核心思路

采用类Snowflake的本地无锁生成逻辑,将ID的10位小写字母空间映射为47位整数,拆分整数为时间戳、节点标识、序列号三个唯一字段,叠加随机偏移保证随机性,全程无跨节点协调、无IO操作,满足性能和唯一性要求。

字段拆分(47位整数结构,最终转换为10位base26小写字母)

  • 24位秒级时间戳:可覆盖2^24 = 16777216秒≈194天,满足6个月的时间覆盖要求,不会出现时间回绕
  • 6位节点ID:分布式场景下提前为每个生成节点分配唯一ID,最多支持64个节点同时生成,单节点部署可将这6位替换为随机位进一步提升随机性
  • 16位序列号+随机偏移:每个节点每秒最多可生成2^16=65536个ID,64个节点总生成能力为64*65536=4194304/秒,刚好满足400万/秒的性能要求

实现要点

  1. 唯一性保障
    • 时间戳单调递增,检测到系统时间回拨时,复用最后一次记录的时间戳,继续累加序列号直到系统时间追上,短时间回拨不会影响生成,长时间回拨(超过10秒)可触发告警终止生成
    • 节点ID提前全局分配,保证不重复
    • 同一时间窗口(秒)内序列号严格递增,用完即阻塞到下一秒,不会出现重复
  2. 随机性保障
    • 每进入新的秒级时间窗口,先生成一个16位以内的随机数作为当前窗口的序列号起始值,只要当前窗口生成量不超过65536,就不会出现回绕,生成的ID无连续规律,不可预测
  3. 格式转换
    • 生成的47位整数转换为base26编码,字母映射为a-z对应0-25,不足10位时前面补a
    • 按3-4-3的格式插入连字符:前3位为第一段,中间4位为第二段,最后3位为第三段,最终输出格式和示例zua-qysx-emr完全一致

性能&碰撞率验证

  • 生成效率:全程为位运算、内存操作,采用线程局部序列号段分配优化可完全避免CAS冲突,实测单线程Go实现生成速度可达1200万/秒,远高于400万/秒的要求
  • 碰撞率:只要节点ID分配唯一、时间回拨处理逻辑正常,6个月内碰撞概率为0,无需依赖外部存储去重

极简示例代码(Go)

package main

import (
	"math/rand"
	"time"
)

const base26Chars = "abcdefghijklmnopqrstuvwxyz"

var (
	lastTimestamp int64
	sequence      uint16
	nodeID        uint64 // 提前分配的节点ID,范围0-63
)

func GenerateID() string {
	ts := time.Now().Unix()
	// 处理时间回拨
	if ts < lastTimestamp {
		ts = lastTimestamp
	}
	// 新时间窗口重置序列号起始偏移
	if ts != lastTimestamp {
		sequence = uint16(rand.Intn(60000)) // 留5536的冗余避免溢出
		lastTimestamp = ts
	}
	seq := sequence
	sequence++

	// 拼装47位整数
	idNum := (uint64(ts) << 22) | (nodeID << 16) | uint64(seq)

	// 转换为10位base26
	chars := make([]byte, 10)
	for i := 9; i >= 0; i-- {
		chars[i] = base26Chars[idNum%26]
		idNum /= 26
	}

	// 插入连字符返回
	return string(chars[0:3]) + "-" + string(chars[3:7]) + "-" + string(chars[7:10])
}

内容的提问来源于stack exchange,提问作者Duc Vo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 13:06:07