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

如何实现高可用且多实例无重复输出的增量式token id生成器

高可用增量全局唯一Token ID生成器技术方案

核心需求确认

你需要的生成器核心特性为:多实例部署下绝对不生成重复ID、ID整体呈增量趋势、服务高可用,以下是生产级可落地的两类实现方案:

可选实现方案

1. 号段预分配模式

这是工业界最常用的方案,核心逻辑是给每个实例预先分配独占的连续ID区间,本地消耗完再重新申请:

  • 实现逻辑
    • 维护一张全局号段分配表,存储每个业务线的当前最大已分配ID、号段步长等信息
    • 每个实例启动或当前号段即将耗尽时,向号段管理服务发起申请,通过事务性操作抢占一段独占ID区间,例如步长为1000时,实例申请到的区间为[1001,2000],其他实例不会再拿到这个区间的ID
    • 实例在本地内存中维护当前号段的剩余ID计数,按顺序生成即可
  • 优势
    • 绝对唯一:号段分配操作是原子性的,不存在重复分配的可能
    • 性能极高:绝大多数请求在本地生成ID,无需跨网络调用,单实例QPS可达10万以上
    • 增量保证:ID整体是趋势递增的,单个实例内部生成的ID严格连续递增
    • 高可用:实例拿到号段后,即使号段管理服务短时间宕机,也可以继续生成ID,只要在号段消耗完成前恢复服务即可
    • 灵活度高:步长可根据业务QPS动态调整,支持多业务线隔离
  • 优化点
    • 可以提前预申请下一个号段,避免当前号段耗尽时等待申请的阻塞问题

2. 雪花算法(Snowflake)变种方案

完全本地化生成的方案,不需要依赖任何外部服务,核心是对64位Long型ID的位数做拆分:

  • 实现逻辑
    • 标准64位ID拆分规则:1位固定符号位(恒为0,保证ID为正) + 41位毫秒级时间戳(可支持使用69年) + 10位全局唯一工作机器ID + 12位单毫秒内序列号(单毫秒最多生成4096个ID)
    • 唯一保证:只要所有实例的工作机器ID全局唯一,就不会生成重复ID
    • 工作机器ID可通过配置中心统一分配、实例IP+端口哈希、容器环境Pod唯一标识生成等方式保证唯一性
  • 优势
    • 无外部依赖:完全本地生成,性能最高,单实例QPS可达百万级别
    • 增量保证:ID按时间戳递增,整体呈严格的时间顺序递增
    • 高可用:只要实例本身可用就能生成ID,不存在外部单点故障
  • 注意事项
    • 必须解决时钟回拨问题:可通过时钟回拨等待、预留序列号位兜底、绑定实例时钟校验规则等方式处理
    • 可根据业务需求调整位数分配:例如需要更多实例时,可将工作机器ID调整为12位,最多支持4096个实例同时运行

选型建议

如果业务要求ID严格全局连续递增,优先选择号段预分配模式;如果追求极致性能、希望减少外部依赖,选择解决了时钟回拨问题的雪花算法变种方案。

高可用保障措施

  • 号段模式下,号段分配的数据库需要做主从集群+自动故障切换,保证号段申请链路的可用性
  • 不管选择哪种方案,都需要部署旁路校验监控:抽样采集生成的ID落库,定期校验是否存在重复ID,出现异常立即告警
  • 生成器实例跨可用区部署,避免单可用区故障导致服务完全不可用

核心代码示例

号段表结构

CREATE TABLE `id_segment` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `biz_type` varchar(64) NOT NULL COMMENT '业务类型标识',
  `current_max_id` bigint NOT NULL DEFAULT '0' COMMENT '当前已分配的最大ID',
  `step` int NOT NULL COMMENT '号段步长',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_biz_type` (`biz_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='ID号段分配表';

号段申请逻辑

// 事务性申请号段
@Transactional(rollbackFor = Exception.class)
public Segment applyNewSegment(String bizType) {
    // 原子更新当前最大ID
    jdbcTemplate.update("UPDATE id_segment SET current_max_id = current_max_id + step WHERE biz_type = ?", bizType);
    // 查询更新后的号段信息
    Map<String, Object> segInfo = jdbcTemplate.queryForMap("SELECT current_max_id, step FROM id_segment WHERE biz_type = ?", bizType);
    Long maxId = (Long) segInfo.get("current_max_id");
    Integer step = (Integer) segInfo.get("step");
    // 返回当前实例独占的号段区间
    return new Segment(maxId - step + 1, maxId);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 01:45:02