# Distributed Id

> Use when generating order numbers, primary keys, or globally unique IDs (雪花, ASSIGN_ID, segment). Do not use UUID as a clustered InnoDB primary key. Do not use for shard-key design (backend-sharding).

- Skill: `1398281322-a11y/distributed-id` (Agent Skill)
- Install (CLI): `npx skillmds@latest add 1398281322-a11y/distributed-id`
- Raw SKILL.md: https://api.skillmd.com/api/skills/1398281322-a11y/distributed-id/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: 1398281322-a11y (https://skillmd.com/u/1398281322-a11y)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/1398281322-a11y/distributed-id

---


# 分布式 ID

## When to Invoke

订单号、主键、分片后的全局唯一 ID、券码。

## When NOT

单库自增已经够且永不拆库的内部表可以继续 AUTO_INCREMENT。分片键怎么选 → `sharding`。

## 风险（面试考点）

UUID 做 InnoDB 主键：无序，页分裂，插入变慢。单机 AUTO_INCREMENT 无法跨库。雪花 ID 依赖时钟，回拨会撞号。号段模式要防 Redis/DB 号段丢失导致重复。

## 适用场景

- 微服务多库的主键
- 订单号对外暴露（可含时间/分片信息）
- 分库分表后的全局唯一

## 方案选型（轻量优先）

| 优先级 | 方案 | 说明 |
|--------|------|------|
| 1 | MyBatis-Plus `IdType.ASSIGN_ID`（雪花） | 默认 |
| 2 | 号段（DB/Redis 一次取一段） | 要可控、趋势递增 |
| 3 | 数据库 AUTO_INCREMENT | 单库内部表 |
| 禁止 | UUID 主键 | 可当业务展示码，不当聚簇主键 |

对外订单号可以：时间 + 分片 + 序列，和内部主键分开。

## 默认方案

```java
@TableId(type = IdType.ASSIGN_ID)
private Long id;
```

时钟：NTP 约束；workerId 按实例稳定分配（配置/K8s ordinal），不要每次随机。回拨：拒绝启动或等待，不要默默发号。

号段：

```sql
UPDATE id_segment SET max_id = max_id + step, version = version + 1
WHERE biz = 'order' AND version = #{version};
-- 本地内存发号，用完再取
```

## 反例

错误：`UUID.randomUUID()` 当主键。
正确：雪花 Long，或 UUID 只做非主键列。

错误：多实例共用 `workerId=1`。
正确：workerId 唯一。

错误：用雪花当用户分片键（时间热点）。
正确：分片键用 `user_id`，ID 只保证唯一。

## 验证

- 多实例并发插入无主键冲突。
- 主键大致时间有序，插入不疯狂页分裂。
- 人为时钟回拨有保护。

## 评审清单

- [ ] 主键不是 UUID
- [ ] workerId 不冲突
- [ ] 订单号与主键是否需要分离已想过
- [ ] 没有用 ID 算法冒充分片设计
---

