在分布式系统中,生成全局唯一、有序且高性能的 ID 是核心需求。以下是几种主流方案的对比与选型建议。

1. 雪花算法 (Snowflake)

Twitter 开源的经典方案,生成 64 位 Long 型 ID。

结构

  • 1 bit: 符号位 (始终为 0)。
  • 41 bits: 时间戳 (毫秒级,可用约 69 年)。
  • 10 bits: 机器 ID (5 位数据中心 ID + 5 位工作机器 ID)。
  • 12 bits: 序列号 (毫秒内自增,支持每毫秒 4096 个 ID)。

优缺点

  • 优点:
    • 高性能: 本地生成,无网络开销,TPS 极高。
    • 有序性: 趋势递增,对数据库 B+ 树索引友好。
    • 不依赖 DB: 避免了单点故障。
  • 缺点:
    • 强依赖时钟: 若机器时钟回拨,可能导致 ID 重复 (需通过等待或抛异常处理)。

2. 数据库号段模式 (Segment)

美团 Leaf、滴滴 TinyID 等中间件的核心机制。

原理

不每次请求数据库,而是从数据库领一个“号段” (如 1000-2000) 加载到内存,用完后再领下一个。

优缺点

  • 优点:
    • 高可用: 数据库宕机短时间内不影响服务 (内存中有缓存号段)。
    • 高性能: 大幅减少数据库 IO。
  • 缺点:
    • ID 不随机: 可能暴露业务量 (如订单号连续)。

3. Redis 生成 (INCR)

利用 Redis 的原子性操作 INCRINCRBY

优缺点

  • 优点: 实现简单,性能优于数据库,天然有序。
  • 缺点:
    • 运维成本: 需维护 Redis 高可用集群。
    • 持久化风险: RDB/AOF 可能存在数据丢失或重复风险。

4. UUID

优缺点

  • 优点: 本地生成,代码简单,全球唯一。
  • 缺点:
    • 无序: 导致 B+ 树索引频繁分裂,写入性能差 (主键大忌)。
    • 存储大: 36 字符 (String),占用空间大。
    • 无业务含义

5. 数据库自增 ID (Flicker 方案)

利用 MySQL 的 replace intoauto_increment,通过设置不同 起始值步长 支持多主架构。

  • 示例: 机器 A (1, 3, 5…), 机器 B (2, 4, 6…)。
  • 缺点: 扩展困难 (加机器需调整步长),数据库仍是瓶颈。

总结建议

场景推荐方案
一般业务Snowflake (或百度 UidGenerator)
对连续性/安全性有要求号段模式 (如美团 Leaf-segment)
主键生成避免使用 UUID