讲师中心 微信公众号
AI工具推荐 视频效率加速

C++如何构建一个毫秒级的分布式唯一ID生成器?(Snowflake算法实现)

酷芳小哥_4200

酷芳小哥_4200

发布时间:2026-03-06 12:26:03

|

813人浏览过

|

来源于php中文网

原创

Snowflake ID生成需时间戳、机器ID、序列号三者组合,仅靠steady_clock毫秒级时间戳会因并发导致重复;须用atomic序列号并毫秒跳变时重置;时间回拨必须拒绝生成而非降级处理。

c++如何构建一个毫秒级的分布式唯一id生成器?(snowflake算法实现)

为什么不能直接用 std::chrono::steady_clock::now().time_since_epoch().count()

毫秒级精度下,单纯靠时间戳会撞 ID:同一毫秒内多个线程/进程调用,count() 返回相同值。Snowflake 要求「时间 + 机器标识 + 序列号」三者组合,缺一不可。C++ 没有内置分布式上下文,你得自己管好 datacenterId 和 workerId 的分配和冲突检测——别指望编译期常量或配置文件硬编码能扛住多实例部署。

std::atomic<uint64_t></uint64_t> 是序列号的唯一合理选择

每台机器每毫秒内可能生成多个 ID,序列号必须原子递增且不重置。用 std::mutex 会严重拖慢吞吐,实测在 4 核机器上压测,锁方式 QPS 往往卡在 2–3 万;而 std::atomic<uint64_t></uint64_t> 配合 fetch_add 可轻松突破 50 万+/s。注意两点:

  • 序列号只在当前毫秒内有效,时间戳跳变时必须清零(不是归零,是重置为 0)
  • 序列号位宽决定单毫秒最大生成数,比如留 12 位就最多 4096 个,超了要阻塞等待下一毫秒(别溢出!)
  • 清零操作本身不是原子的,需用 if (currentMs != lastMs) { seq.store(0); lastMs = currentMs; },且 lastMs 也得是 std::atomic

时间回拨问题比想象中更常见

物理机 NTP 校时、容器被调度暂停、云主机休眠唤醒,都可能导致 std::chrono::system_clock 或 steady_clock 突然倒退。一旦发生,按 Snowflake 原则应拒绝生成 ID 并报错(如抛出 std::runtime_error("Clock moved backwards")),而不是强行用旧时间戳拼 ID——否则 ID 重复概率陡增。更稳妥的做法:

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • 优先用 std::chrono::steady_clock 获取单调递增时间(但它不等于真实时间,需定期对齐 system_clock)
  • 记录上次生成 ID 的时间戳(lastTimestamp),每次生成前比较:if (ts
  • 允许小范围容忍(如 5ms 内回拨可等待,超过则报错),但别自动补偿——补偿逻辑极易引入隐式状态和竞态

机器 ID 分配必须脱离代码硬编码

把 datacenterId 和 workerId 写死在源码里,上线后改一个就得全量重启。实际部署中,它们应该来自外部:

立即学习“C++免费学习笔记(深入)”;

  • 环境变量:getenv("SNOWFLAKE_DATACENTER_ID") + getenv("SNOWFLAKE_WORKER_ID"),启动时校验范围(0–31 合理)
  • Kubernetes 场景下,可用 Downward API 注入 Pod IP 的哈希后取模,但要注意哈希碰撞——建议结合节点 label 或 StatefulSet 序号
  • 绝对不要用 MAC 地址或 PID 做 workerId:容器里 MAC 经常重复,PID 会回收复用

ID 位布局一旦上线就不能动,比如默认 41+10+12=63 位,其中 10 位 workerId 最大支持 1024 个节点——超了就得改协议,客户端兼容性立马崩。这事没法热更新。

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

相关专题

更多
什么是分布式
什么是分布式

分布式是一种计算和数据处理的方式,将计算任务或数据分散到多个计算机或节点中进行处理。本专题为大家提供分布式相关的文章、下载、课程内容,供大家免费下载体验。

2053

2023.08.11

分布式和微服务的区别
分布式和微服务的区别

分布式和微服务的区别在定义和概念、设计思想、粒度和复杂性、服务边界和自治性、技术栈和部署方式等。本专题为大家提供分布式和微服务相关的文章、下载、课程内容,供大家免费下载体验。

3174

2023.10.07

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6104

2023.10.24

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3208

2023.11.20

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

4258

2023.08.10

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

6036

2023.08.14

Golang云原生微服务Kubernetes_Golang怎么集成Kubernetes开发云原生服务
Golang云原生微服务Kubernetes_Golang怎么集成Kubernetes开发云原生服务

Golang云原生微服务Kubernetes (K8s) 是指 使用 Go 语言(Golang)编写的云原生微服务,并利用 Kubernetes 平台进行容器化部署、自动化管理、弹性伸缩和高效编排的一整套现代应用架构方案。

116

2025.12.22

Go云原生应用与Kubernetes服务部署实战
Go云原生应用与Kubernetes服务部署实战

本专题围绕 Go 语言在云原生环境中的应用展开,讲解容器化部署、Kubernetes 编排、服务发现、健康检查与弹性扩缩容机制。通过真实云端案例,帮助开发者构建可扩展的云原生微服务架构。

188

2026.06.29

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

0

2026.10.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn