分布式 ID
分布式 ID 完整选型 落地方案生产可用分场景直接选一、主流 5 种方案优缺点总览1. UUID / UUID36优点本地生成无 RPC、简单缺点无序、太长 36 位、数据库索引差、泄露 MAC 地址旧版适用简单日志、临时业务 ID严禁做主键2. 数据库自增主键单库优点连续有序、稳定、最简单缺点单点瓶颈分库分表完全不能用适用单体小型系统3. 数据库号段模式Leaf、百度 UidGenerator原理业务一次性批量拿一段 ID 缓存本地用完再去 DB 申请下一号段优点有序、性能极高、稳定、可持久化、故障不重复缺点需要单独一张号段表轻微开发量适用绝大多数企业业务、订单、财务、主业务主键最稳妥通用选型4. Redis INCR / 号段优点性能爆炸原子自增缺点宕机丢未持久化增量、依赖 Redis 集群稳定性适用高并发秒杀、临时流水号5. Snowflake 雪花算法Twitter64bit 结构时间戳 (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三大致命坑 解决方案时钟回拨最严重现象服务器 NTP 同步回拨生成重复 ID解决本机记录上一次生成时间当前时间 上次时间 → 直接抛出异常 / 自旋等待Leaf 雪花自带时间回拨补偿禁止虚拟机时间漂移机器 ID 重复方案启动注册到 Zookeeper/Redis自动分配唯一机器号物理机用 IP 最后 10 位、容器用 K8s pod 固定标识单机毫秒内 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 );示例初始化一条ordermax_id10000step10002. 运行逻辑服务启动拉取一段10001~11000 缓存在内存业务直接内存取号无 DB 请求内存剩余 10% 阈值异步去 DB 抢占下一段号段CAS 更新 max_id数据库只有简单 UPDATEupdate id_segment set max_id max_id step where business_tag ?原子更新绝对不会重复3. 优势DB 宕机内存号段还能继续支撑很久完全没有时钟问题金融财务零风险有序数字 IDMySQL 主键索引性能拉满五、开源成熟框架直接落地不用重复造轮子美团 Leaf首选两种模式自由切换Segment 号段 Snowflake 支持监控、号段自动扩容、雪花时钟回拨处理、RPC 接入简单百度 UidGenerator基于雪花借助 Redis 解决机器 ID 与时钟滴滴 TinyId纯号段方案轻量六、Java 生产极简落地建议企业内部管理系统、MES、WMS、财务单据采用Leaf Segment 号段高并发 C 端业务、千万级订单采用Leaf Snowflake 模式开启时钟回拨保护禁止自己手写简易雪花时钟回拨一定会踩坑七、分库分表配套规则雪花 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) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT分布式号段表; -- 初始化测试数据 INSERT INTO id_segment(business_tag,max_id,step) VALUES (order,10000,2000);2、MyBatis MapperMapper 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 MapString, 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 分配方案物理机IP最后两段取模1024K8s 容器注册到 Redis/ZK 自动分配唯一 workerId三、SpringBoot 接入美团 Leaf 完整配置生产首选1、架构选择同时部署Segment 号段做主业务 IDSnowflake 做高并发流水 ID2、application.ymlleaf: segment: enable: true url: jdbc:mysql://localhost:3306/leaf_db?useUnicodetrue username: root password: xxx snowflake: enable: true # 使用ZK自动分配workerId杜绝重复 zk-address: 127.0.0.1:21813、依赖 Mavendependency groupIdcom.sankuai.inf.leaf/groupId artifactIdleaf-core/artifactId version1.0.4/version /dependency4、注入使用Autowired private SegmentIDGenImpl segmentIDGen; Autowired private SnowflakeIDGenImpl snowflakeIDGen; // 号段ID订单、财务单据 Long orderId segmentIDGen.get(order).getId(); // 雪花ID高并发流水 Long flowId snowflakeIDGen.get(flow).getId();四、三种方案选型极简总结MES/WMS/ 财务 / ERP 单据、要求绝对稳定无时钟风险→ 自研号段 / Leaf Segment高并发千万级 C 端订单、海量数据→ 安全雪花 / Leaf 雪花小型单体项目→ 简单雪花即可

相关新闻

Belt工具库在实际项目中的应用案例分享

Belt工具库在实际项目中的应用案例分享

Belt工具库在实际项目中的应用案例分享 【免费下载链接】belt A handful of tools for PHP developers. 项目地址: https://gitcode.com/gh_mirrors/be/belt Belt工具库是一款专为PHP开发者打造的实用工具集,提供了丰富的数组操作、集合处理等功能&#xff0…

2026/7/22 23:36:14 阅读更多 →
Node API for .NET完全指南:如何在JavaScript中无缝调用.NET API

Node API for .NET完全指南:如何在JavaScript中无缝调用.NET API

Node API for .NET完全指南:如何在JavaScript中无缝调用.NET API 【免费下载链接】node-api-dotnet Advanced interoperability between .NET and JavaScript in the same process. 项目地址: https://gitcode.com/gh_mirrors/no/node-api-dotnet Node API f…

2026/7/22 23:36:14 阅读更多 →
OpenClaw小龙虾部署教程,本地与云端全平台方案

OpenClaw小龙虾部署教程,本地与云端全平台方案

一、本地部署:手把手教你搭建“小龙虾”厨房 夏天到了,谁能拒绝一盘麻辣鲜香的小龙虾?可你知道吗,在程序员的世界里,也有一道名为“OpenClaw小龙虾”的硬菜——它不是什么网红美食,而是一套开源的网络爬虫部…

2026/7/22 23:36:14 阅读更多 →

最新新闻

垂直领域的那些事儿——遥感、医疗、工业质检,各有各的苦

垂直领域的那些事儿——遥感、医疗、工业质检,各有各的苦

最后一篇了,咱们不聊通用分割了,聊聊垂直领域。这些领域里的语义分割,玩的逻辑跟学术数据集完全是两码事。先说 遥感图像分割。这玩意儿的分辨率动不动就是 0.5 米到 2 米每像素,一张图覆盖几平方公里,尺寸可达 10000x…

2026/7/23 0:17:29 阅读更多 →
计算机毕业设计之作业管理系统

计算机毕业设计之作业管理系统

随着信息技术和网络技术的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息。为了迎合时代需求,优化管理效率,各种各样的管理系统应运而生,各行各业相继进入信息管理时代&#xf…

2026/7/23 0:17:29 阅读更多 →
多模态融合——RGB不够,Depth来凑,语言也来插一脚

多模态融合——RGB不够,Depth来凑,语言也来插一脚

干了这么多年视觉,你要是只会处理 RGB 图,出去都不好意思跟人聊。现在的趋势很明显——单模态已经到头了。RGB 再有本事,遇到夜间场景、强反光、遮挡严重的情况,照样抓瞎。怎么办?加传感器,多模态融合。最早…

2026/7/23 0:17:29 阅读更多 →
损失函数与训练细节——这些坑我替你踩过了

损失函数与训练细节——这些坑我替你踩过了

先聊聊 Loss 函数。语义分割最基础的 Loss 是 Cross-Entropy(交叉熵),简单粗暴,逐像素计算分类损失。但你很快会发现一个问题——类别不平衡。Cityscapes 里“道路”和“建筑”占了画面大半江山,而“摩托车”、“自行车…

2026/7/23 0:17:29 阅读更多 →
SunnyUI.Net更新:基于多框架的开源控件库,V3.9.8修复多项问题

SunnyUI.Net更新:基于多框架的开源控件库,V3.9.8修复多项问题

SunnyUI.Net是基于多个.Net框架的C# WinForm开源控件库等。近日迎来V3.9.8版本更新,修复了一些关键问题。项目简介SunnyUI.Net是基于.Net Framework 4.0 - 4.8、.Net8、.Net9框架的C# WinForm开源控件库,还包含工具类库、扩展类库和多页面开发框架&#…

2026/7/23 0:15:29 阅读更多 →
告别TensorFlow?PyTorch入门指南:为什么它是研究界的首选框架

告别TensorFlow?PyTorch入门指南:为什么它是研究界的首选框架

引言:一场关于“更好”的辩论 在深度学习的开发者社区里,有一个经久不衰的话题:PyTorch和TensorFlow,到底哪个更好?这个问题的答案往往取决于提问者的背景——如果你问一位高校的研究员,他大概率会回答“Py…

2026/7/23 0:15:29 阅读更多 →

日新闻

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…

2026/7/23 0:00:25 阅读更多 →
AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

更多请点击: https://codechina.net 第一章:AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析 在对2,346篇跨行业AI生成文案的A/B测试数据进行聚类分析后,我们发现&#xff1…

2026/7/23 0:01:26 阅读更多 →
Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具 【免费下载链接】chitchatter Secure peer-to-peer chat that is serverless, decentralized, and ephemeral 项目地址: https://gitcode.com/gh_mirrors/ch/chitchatter Chitchatter是一款革命性的安…

2026/7/23 0:01:26 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 8:58:19 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 19:43:43 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/22 12:54:44 阅读更多 →

月新闻