面试级「分布式 ID 设计方案」

目标 → 主流方案 → 对比 → 实战选型 → 源码级思想 ,适合 P6~P7 / 架构岗,可以直接背,也可以当系统设计题来答。


一、分布式 ID 的设计目标(面试开场)

分布式 ID 是跨服务、跨库、跨机器的唯一标识,设计时要满足:

全局唯一(最基本)

趋势递增(MySQL B+Tree 友好)

高性能(高并发下不成为瓶颈)

高可用(不能依赖单点)

易接入(业务无感)

可解析(排查问题方便)


二、常见分布式 ID 方案总览

方案 唯一性 递增 性能 复杂度 推荐指数
UUID ⭐⭐
数据库自增 ⭐⭐
数据库号段 ⭐⭐ ⭐⭐⭐⭐
Redis 自增 ⭐⭐ ⭐⭐⭐
Snowflake ✅✅ ⭐⭐⭐ ⭐⭐⭐⭐⭐
Leaf / TinyID ✅✅ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐

三、主流方案详解(重点)


1️⃣ UUID(不推荐)

复制代码
UUID.randomUUID().toString();

优点

✅ 简单

✅ 无网络开销

✅ 本地生成

缺点(致命)

无序​ → MySQL 页分裂

❌ 太长(36 位字符串)

❌ 无业务含义

❌ 不易排查问题

👉 结论:只适合临时标识,不适合业务 ID


2️⃣ 数据库自增 ID(单机 OK)

复制代码
CREATE TABLE order (
  id BIGINT AUTO_INCREMENT PRIMARY KEY
);

优点

✅ 简单

✅ 严格递增

缺点

❌ 单点

❌ 性能瓶颈

❌ 分库分表困难

👉 结论:单体系统可用,分布式不行


3️⃣ 数据库号段模式(推荐)

本质是:批量取号,内存发号

原理

复制代码
DB 只存最大值
每次取 1000 个号
缓存在内存中
用完再取

表结构

复制代码
CREATE TABLE id_segment (
  biz_tag VARCHAR(32) PRIMARY KEY,
  max_id BIGINT,
  step INT
);

发号逻辑

复制代码
update id_segment
set max_id = max_id + step
where biz_tag = 'order';

优点

✅ 高性能

✅ 趋势递增

✅ 弱依赖 DB

缺点

❌ 依赖 DB

❌ 重启可能浪费 ID

中小规模系统非常合适


4️⃣ Redis 自增(简单但有限)

复制代码
INCR order:id

优点

✅ 快

✅ 简单

✅ 原子性

缺点

❌ Redis 宕机风险

❌ 重启可能重复(需持久化)

❌ 无时间戳信息

👉 适合非核心业务


5️⃣ Snowflake(最主流 ⭐⭐⭐⭐⭐)

Twitter 开源,工业级方案

ID 结构(64 bit)

复制代码
| 1 bit | 41 bit 时间戳 | 10 bit 机器ID | 12 bit 序列号 |

0 | 0000000000000000000000000000000000000 | 0000000000 | 000000000000

各部分含义

位段 长度 说明
符号位 1 固定 0
时间戳 41 毫秒级
机器 ID 10 数据中心 + 工作节点
序列号 12 同一毫秒内自增

特点

趋势递增

本地生成

高性能

无依赖

问题点(面试必问)

问题 解决方案
时钟回拨 等待 / 抛异常 / 用上次时间
机器 ID 分配 Zookeeper / 配置中心
序列号耗尽 等到下一毫秒

Snowflake 代码示例(精简版)

复制代码
public class SnowflakeIdGenerator {

    private final long workerId;
    private final long epoch = 1700000000000L;
    private long sequence = 0L;
    private long lastTimestamp = -1L;

    public SnowflakeIdGenerator(long workerId) {
        this.workerId = workerId;
    }

    public synchronized long nextId() {
        long timestamp = System.currentTimeMillis();

        if (timestamp < lastTimestamp) {
            throw new RuntimeException("时钟回拨");
        }

        if (timestamp == lastTimestamp) {
            sequence = (sequence + 1) & 4095;
            if (sequence == 0) {
                timestamp = waitNextMillis(timestamp);
            }
        } else {
            sequence = 0;
        }

        lastTimestamp = timestamp;

        return ((timestamp - epoch) << 22)
                | (workerId << 12)
                | sequence;
    }

    private long waitNextMillis(long timestamp) {
        while (timestamp <= lastTimestamp) {
            timestamp = System.currentTimeMillis();
        }
        return timestamp;
    }
}

6️⃣ 号段模式增强版:Leaf / TinyID(大厂方案)

核心思想

DB + 缓存 + 双 Buffer

  • 一个号段快用完时
  • 异步加载下一个号段
  • 无阻塞切换

美团 Leaf、滴滴 TinyID 都是这个思路

👉 适合高并发、核心业务


四、方案选型建议(面试总结用)

场景 推荐方案
单体系统 数据库自增
中小规模 数据库号段
高并发核心 Snowflake
大厂级 Leaf / TinyID
非核心业务 Redis / UUID

五、面试 5 分钟口述版(直接背)

面试官:如何设计分布式 ID?

参考回答:

分布式 ID 的核心目标是全局唯一、趋势递增、高性能和高可用。常见方案有 UUID、数据库自增、数据库号段、Redis 自增和 Snowflake。
UUID 虽然简单,但无序且太长,不适合作为数据库主键;数据库自增在分库分表场景下会成为瓶颈;数据库号段模式通过批量取号、内存发号,性能和可用性都不错,适合中小规模系统;Redis 自增依赖 Redis 的可用性,适合非核心业务。
目前最主流的是 Snowflake 算法,它利用时间戳、机器 ID 和序列号生成 64 位 Long 型 ID,趋势递增、本地生成、性能非常高,是 Twitter 开源的工业级方案。实际使用时会遇到时钟回拨问题,可以通过等待或异常方式处理,机器 ID 可以通过 Zookeeper 或配置中心分配。
在大规模场景下,像美团 Leaf、滴滴 TinyID 这样的号段增强方案,通过双 Buffer 预加载,进一步提升了稳定性和性能。
实际选型时,我会根据业务规模和一致性要求来决定,核心业务优先 Snowflake 或 Leaf,非核心业务可以考虑 Redis 或号段模式。


六、一句话总结(收尾金句)

"分布式 ID 没有万能方案,核心是在唯一性、性能和可维护性之间做权衡,Snowflake 是目前最成熟、最通用的选择。"


七、面试官常追问 & 标准答法

追问 回答
Snowflake 时钟回拨怎么办? 等待 / 抛异常 / 使用上次时间
机器 ID 怎么分配? Zookeeper / 配置中心 / 启动时分配
为什么 ID 要趋势递增? 减少 MySQL 页分裂
号段模式浪费 ID 怎么办? 可接受,用可维护性换性能
分布式 ID 能包含业务信息吗? 可以,但不建议,ID 应解耦业务
相关推荐
青春易逝丶1 小时前
Maven
java·maven
吠品1 小时前
纯HTML+ECharts构建交互式数据看板:实现思路与踩坑记录
java·服务器·数据库
盖伦发发1 小时前
Redis 核心教学: 数据结构, 缓存设计, 分布式锁
java·redis·后端·软件工程
卷毛的技术笔记1 小时前
RocketMQ事务消息:我把分布式事务这层窗户纸捅破了
java·分布式·后端·java-rocketmq
yxlalm2 小时前
零基础快速上手Trae创建Java项目
java·人工智能
ly76892 小时前
磁盘 I/O 延迟突增:用 iostat、blktrace 与火焰图定位到具体调用栈
java·linux·前端·数据库·iostat·磁盘 i/o·blktrace
泡海椒2 小时前
jquick-pdf 核心原理解析:基于 HTML 模板动态渲染 PDF 的实现逻辑
java·开发语言·pdf
Bs_MoneyMagnet2 小时前
基于springboot+vue的图书馆预约系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·毕业设计·图书管理系统·计算机毕业设计
小蒜学长2 小时前
基于小程序的绘画作品创作与分享社区系统的设计与实现(代码+数据库+LW)
java·spring boot·后端·绘画作品·创作分享社区