尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

分布式 ID

分布式 ID
📅 发布时间:2026/7/22 23:37:58

分布式 ID 完整选型 + 落地方案(生产可用,分场景直接选)

一、主流 5 种方案优缺点总览

1. UUID / UUID36

  • 优点:本地生成,无 RPC、简单
  • 缺点:无序、太长 36 位、数据库索引差、泄露 MAC 地址(旧版)
  • 适用:简单日志、临时业务 ID,严禁做主键

2. 数据库自增主键(单库)

  • 优点:连续有序、稳定、最简单
  • 缺点:单点瓶颈,分库分表完全不能用
  • 适用:单体小型系统

3. 数据库号段模式(Leaf、百度 UidGenerator)

原理:业务一次性批量拿一段 ID 缓存本地,用完再去 DB 申请下一号段

  • 优点:有序、性能极高、稳定、可持久化、故障不重复
  • 缺点:需要单独一张号段表,轻微开发量
  • 适用:绝大多数企业业务、订单、财务、主业务主键(最稳妥通用选型)

4. Redis INCR / 号段

  • 优点:性能爆炸,原子自增
  • 缺点:宕机丢未持久化增量、依赖 Redis 集群稳定性
  • 适用:高并发秒杀、临时流水号

5. Snowflake 雪花算法(Twitter)

64bit 结构:时间戳 (41)+ 机器 ID (10)+ 序列号 (12)

  • 优点:全局有序、纯本地生成、不依赖第三方、64 位 long 型
  • 缺点:时钟回拨致命问题、机器 ID 要手动分配维护
  • 适用:高并发互联网业务、海量数据场景;必须解决时钟回拨

6. 美团 Leaf(同时支持雪花 + 号段)

企业级成熟开源框架,直接拿来用,业界落地最多。

二、明确选型决策表(直接对照业务选)

场景 1:传统 ERP/MES/ 财务 / 支付、要求绝对不重复、数据稳妥

✅优先:Leaf 号段模式

  • 强一致性、无时钟问题、运维简单、数据库可溯源
  • 分库分表天然支持

场景 2:超高并发、百万 QPS、海量流水、不在乎短暂时钟风险

✅Snowflake(自研 / Leaf 雪花模式)必须配套:时钟监控、回拨拒绝策略、机器 ID 注册中心

场景 3:简单临时 ID、内部埋点、非主键

✅ UUID / 简单雪花

场景 4:秒杀短时效流水号

✅ Redis 自增

三、雪花算法详细落地关键点(避坑核心)

64 位标准结构

1bit 符号位 | 41bit 毫秒时间戳 | 10bit 机器 ID | 12bit 序列号

  • 机器 ID 10bit:最多 1024 台机器
  • 序列号 12bit:每毫秒单节点最多 4096 个 ID

三大致命坑 & 解决方案

  1. 时钟回拨(最严重)
  • 现象:服务器 NTP 同步回拨,生成重复 ID
  • 解决:
    • 本机记录上一次生成时间,当前时间 < 上次时间 → 直接抛出异常 / 自旋等待
    • Leaf 雪花自带时间回拨补偿
    • 禁止虚拟机时间漂移
  1. 机器 ID 重复
  • 方案:
    • 启动注册到 Zookeeper/Redis,自动分配唯一机器号
    • 物理机用 IP 最后 10 位、容器用 K8s pod 固定标识
  1. 单机毫秒内 4096 序列号耗尽
  • 自旋等到下一毫秒即可

四、号段模式落地架构(强烈推荐制造业 / 企业系统)

1. 单独号段数据表

CREATE TABLE id_segment ( business_tag VARCHAR(50) PRIMARY KEY COMMENT '业务标识:order,receivable', max_id BIGINT NOT NULL COMMENT '当前已分配最大号', step INT NOT NULL COMMENT '每次申请步长', update_time DATETIME );

示例初始化一条:order,max_id=10000,step=1000

2. 运行逻辑

  1. 服务启动拉取一段:10001~11000 缓存在内存
  2. 业务直接内存取号,无 DB 请求
  3. 内存剩余 10% 阈值,异步去 DB 抢占下一段号段(CAS 更新 max_id)
  4. 数据库只有简单 UPDATE:update id_segment set max_id = max_id + step where business_tag = ?
  • 原子更新,绝对不会重复

3. 优势

  • DB 宕机,内存号段还能继续支撑很久
  • 完全没有时钟问题,金融财务零风险
  • 有序数字 ID,MySQL 主键索引性能拉满

五、开源成熟框架直接落地(不用重复造轮子)

  1. 美团 Leaf(首选)两种模式自由切换:Segment 号段 + Snowflake 支持监控、号段自动扩容、雪花时钟回拨处理、RPC 接入简单
  2. 百度 UidGenerator:基于雪花,借助 Redis 解决机器 ID 与时钟
  3. 滴滴 TinyId:纯号段方案,轻量

六、Java 生产极简落地建议

  1. 企业内部管理系统、MES、WMS、财务单据采用:Leaf Segment 号段
  2. 高并发 C 端业务、千万级订单采用:Leaf Snowflake 模式,开启时钟回拨保护
  3. 禁止自己手写简易雪花,时钟回拨一定会踩坑

七、分库分表配套规则

  • 雪花 ID:取 ID 取模分片
  • 号段 ID:同样取模,全局连续完全兼容分片

三套完整可直接投产代码:自研号段工具类 + 安全雪花算法 + SpringBoot 接入美团 Leaf

一、自研数据库号段分布式 ID(企业 ERP/MES/ 财务最稳)

1、号段数据表

CREATE TABLE `id_segment` ( `business_tag` varchar(50) NOT NULL COMMENT '业务标识:order、receivable、work_order', `max_id` bigint NOT NULL DEFAULT 0 COMMENT '已分配最大ID', `step` int NOT NULL DEFAULT 1000 COMMENT '每次申请号段长度', `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`business_tag`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='分布式号段表'; -- 初始化测试数据 INSERT INTO id_segment(business_tag,max_id,step) VALUES ('order',10000,2000);

2、MyBatis Mapper

@Mapper public interface IdSegmentMapper { @Update("UPDATE id_segment SET max_id = max_id + step WHERE business_tag = #{tag}") int increaseSegment(@Param("tag") String tag); @Select("SELECT max_id,step FROM id_segment WHERE business_tag = #{tag}") IdSegment selectByTag(@Param("tag") String tag); } @Data public class IdSegment { private Long maxId; private Integer step; }

3、号段生成器核心工具类

import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.Map; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicLong; @Component public class SegmentIdGenerator { @Resource private IdSegmentMapper idSegmentMapper; // 本地缓存号段 private final Map<String, SegmentBuffer> bufferMap = new ConcurrentHashMap<>(); // 异步预加载线程池 private final ExecutorService pool = Executors.newSingleThreadExecutor(); private static class SegmentBuffer { // 当前号段起始、截止、当前取值 AtomicLong current; long end; int step; volatile boolean isLoading; } public Long nextId(String businessTag) { SegmentBuffer buffer = bufferMap.computeIfAbsent(businessTag, k -> initBuffer(k)); long id = buffer.current.getAndIncrement(); // 剩余10%阈值,异步拉取下一号段 if (id >= buffer.end - buffer.step * 0.1 && !buffer.isLoading) { loadNextAsync(buffer, businessTag); } if (id > buffer.end) { synchronized (buffer) { while (id > buffer.end) { try { buffer.wait(); } catch (InterruptedException e) { throw new RuntimeException("获取号段超时"); } } id = buffer.current.getAndIncrement(); } } return id; } private SegmentBuffer initBuffer(String tag) { IdSegment seg = idSegmentMapper.selectByTag(tag); SegmentBuffer buf = new SegmentBuffer(); buf.step = seg.getStep(); buf.end = seg.getMaxId(); buf.current = new AtomicLong(buf.end - buf.step + 1); return buf; } private void loadNextAsync(SegmentBuffer buffer, String tag) { if (!buffer.isLoading) { buffer.isLoading = true; pool.submit(() -> { try { // CAS原子递增 idSegmentMapper.increaseSegment(tag); IdSegment newSeg = idSegmentMapper.selectByTag(tag); synchronized (buffer) { buffer.end = newSeg.getMaxId(); buffer.current.set(buffer.end - buffer.step + 1); buffer.notifyAll(); } } finally { buffer.isLoading = false; } }); } } }

使用

@Autowired private SegmentIdGenerator segmentIdGenerator; Long orderId = segmentIdGenerator.nextId("order");

二、自带时钟回拨防护的雪花算法(可直接上线)

public class SafeSnowflakeIdGenerator { // 64位划分 private static final long TIME_BIT = 41L; private static final long WORKER_BIT = 10L; private static final long SEQ_BIT = 12L; private static final long MAX_WORKER_ID = (1L << WORKER_BIT) - 1; private static final long MAX_SEQ = (1L << SEQ_BIT) - 1; private static final long WORKER_SHIFT = SEQ_BIT; private static final long TIME_SHIFT = SEQ_BIT + WORKER_BIT; // 基准时间:2025-01-01 private static final long EPOCH = 1735689600000L; private final long workerId; private long lastTime = 0L; private long sequence = 0L; public SafeSnowflakeIdGenerator(long workerId) { if (workerId < 0 || workerId > MAX_WORKER_ID) { throw new IllegalArgumentException("机器ID超出0~1023"); } this.workerId = workerId; } public synchronized long nextId() { long now = System.currentTimeMillis(); // 时钟回拨 if (now < lastTime) { long offset = lastTime - now; // 回拨小于50ms自旋等待,超过直接抛异常拒绝生成 if (offset < 50) { try { Thread.sleep(offset); now = System.currentTimeMillis(); } catch (InterruptedException e) { throw new RuntimeException("时钟回拨,生成ID失败"); } } else { throw new RuntimeException("严重时钟回拨,禁止生成ID"); } } // 同一毫秒自增序列号 if (now == lastTime) { sequence = (sequence + 1) & MAX_SEQ; if (sequence == 0) { // 序列号用尽,等到下一毫秒 while (now <= lastTime) { now = System.currentTimeMillis(); } } } else { sequence = 0; } lastTime = now; return ((now - EPOCH) << TIME_SHIFT) | (workerId << WORKER_SHIFT) | sequence; } }

机器 ID 分配方案

  1. 物理机:IP最后两段取模1024
  2. K8s 容器:注册到 Redis/ZK 自动分配唯一 workerId

三、SpringBoot 接入美团 Leaf 完整配置(生产首选)

1、架构选择

同时部署Segment 号段做主业务 ID,Snowflake 做高并发流水 ID

2、application.yml

leaf: segment: enable: true url: jdbc:mysql://localhost:3306/leaf_db?useUnicode=true username: root password: xxx snowflake: enable: true # 使用ZK自动分配workerId,杜绝重复 zk-address: 127.0.0.1:2181

3、依赖 Maven

<dependency> <groupId>com.sankuai.inf.leaf</groupId> <artifactId>leaf-core</artifactId> <version>1.0.4</version> </dependency>

4、注入使用

@Autowired private SegmentIDGenImpl segmentIDGen; @Autowired private SnowflakeIDGenImpl snowflakeIDGen; // 号段ID(订单、财务单据) Long orderId = segmentIDGen.get("order").getId(); // 雪花ID(高并发流水) Long flowId = snowflakeIDGen.get("flow").getId();

四、三种方案选型极简总结

  1. MES/WMS/ 财务 / ERP 单据、要求绝对稳定无时钟风险→ 自研号段 / Leaf Segment
  2. 高并发千万级 C 端订单、海量数据→ 安全雪花 / Leaf 雪花
  3. 小型单体项目→ 简单雪花即可

相关新闻

  • gh_mirrors/log/logback授权控制详解:基于角色与权限的访问管理
  • 如何用Niva快速构建第一个跨平台桌面应用?5分钟上手教程
  • 【超详细】二分查找(折半查找)核心知识点全解析(含多场景代码实现)

最新新闻

  • 2026年襄阳周边保时捷机油靠谱供应商家实用参考指南 - 热点品牌推荐
  • 2026年老黄历APP推荐:个人历、亲友提醒与传统黄历日历工具如何选型?附天乙日历App完整测评
  • `githooks` 让 Git 找不到 hook**(你手动 `./githooks/commit-msg` 能跑,但 `git commit` 未必用同一个目录)。
  • Runway绿幕抠像不卡顿、不出错、不重渲:GPU显存分配+缓存预加载+代理序列三重加速方案
  • 2026年深圳PEI板生产厂商选购指南及行业实用参考 - 热点品牌推荐
  • 2026年国产三坐标测量仪企业选型实用参考指南 - 奔跑123

日新闻

  • 亨得利盐城维修点在哪里?手表维修保养地址指南**公示(2026年7月最新) - 亨得利官方
  • 提升.NET API安全性:Boxed.AspNetCore.Swagger认证授权最佳实践
  • 帝舵佛山**网点地址更新:2026年7月售后热线电话与服务客户指南 - 帝舵中国官方服务中心

周新闻

  • SaaS软件行业GEO实践:AI搜索时代的品牌可见性与获客新路径
  • 什么是PCTFE?医药高端包装的“防潮王牌“材料
  • 【JVM调优实战】16-可视化利器-JConsole-VisualVM-JMC

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号