在分布式系统中,唯一标识符(Unique ID) 的生成是非常关键的一环。无论是数据库的主键、订单号、日志追踪 ID、消息唯一标识,还是用户唯一编号,都必须保证在分布式部署环境中:
全局唯一性(Global Uniqueness)
高可用与高性能(High Availability & High Throughput)
可扩展性(Scalability)
传统数据库(如 MySQL)的自增 ID 或 UUID 均存在缺陷:
自增 ID 在多节点环境中难以协调;
UUID 虽然全局唯一,但太长(128bit),且无序不可读,影响索引性能。
为解决这些问题,Twitter 在 2010 年提出了著名的 Snowflake(雪花算法),它能在分布式系统中以极高性能生成全局唯一、趋势递增的 64 位 ID。
设计目标:
高效(每秒可生成数百万 ID);
节点间独立生成,无需中心协调;
可支持高并发环境下的线程安全。
本项目旨在使用 C++17 实现完整的 Snowflake 算法生成器,支持多线程同时生成唯一 ID。
ID 组成结构
1bit:符号位(固定为0)
5bit:数据中心ID(0~31)
5bit:机器ID(0~31)
12bit:序列号(每毫秒最多 4096 个)
可配置参数
数据中心ID
机器ID
功能点
支持单线程/多线程环境;
支持跨毫秒序列自增;
支持时钟回拨保护;
生成结果为 int64_t;
可格式化为字符串(用于日志输出);
线程安全。
性能要求
单节点每秒可生成 > 400万 ID;
多线程环境下保证唯一性;
延迟 < 1µs。
兼容性
平台:Linux / Windows / macOS;
详解:
→ 可支持:
每毫秒4096个ID;
每秒 4.096 × 10³ × 10³ = 4百万个;
连续使用 69 年(2⁴¹ 毫秒)。
通过位移(<<)和按位或(|)拼接各个字段:
id = ((timestamp - epoch) << timestampShift) | (datacenterId << datacenterShift) | (workerId << workerShift) | sequence;
反之,也可以通过位移和掩码(&)分离各部分字段。
常见解决方案:
使用备用序列区间;
引入逻辑时钟补偿;
直接报错拒绝生成(本例采用此法)。
多线程场景下多次生成ID可能竞争修改 lastTimestamp 与 sequence。本项目采用:
std::mutex 保护;
可改进为 无锁原子操作 + 自旋锁 优化性能。
使用 std::chrono::system_clock::now() 获取毫秒级时间戳。若同一毫秒内序列耗尽(>4095),则等待下一个毫秒:
while (currTimestamp <= lastTimestamp) currTimestamp = getCurrentTimestamp();
整个雪花算法的实现分为以下步骤:
定义结构体字段常量
位数定义;
最大ID值;
位移量(Shift)。
初始化参数
校验范围合法性。
实现生成函数 nextId()
同毫秒:序列+1;
不同毫秒:序列=0;
回拨:抛异常或等待;
位运算拼接生成ID。
线程安全与性能优化
加锁保护;
测试模块
单线程性能;
多线程唯一性验证;
输出示例。
waitNextMillis():当序列耗尽时等待到下一毫秒。
formatId():用于解析ID结构并输出可读格式(调试用)。
singleThreadTest():演示单线程连续生成10个ID的结果。
multiThreadTest():开启8个线程并发生成ID,最后汇总验证唯一性。
本项目完整实现了 Snowflake 分布式唯一 ID 生成算法的 C++ 版本,其主要特点如下:
✅ 高性能:每毫秒最多生成4096个ID;✅ 全局唯一:由时间戳+数据中心+机器号+序列号组合保证;✅ 线程安全:使用mutex锁保障并发安全;✅ 易扩展:通过调整 bit 分配即可适应更大规模系统;✅ 跨平台:纯标准C++实现,可在Linux/Windows/macOS通用。
Q3:序列号为什么是12位?A3:每毫秒可产生 2¹²=4096 个ID,满足高并发需求。
Q5:多线程是否会冲突?A5:不会,本实现使用 mutex 保证线程安全。高性能版本可使用原子锁或CAS优化。
高性能无锁版本
使用 std::atomic 实现无锁自增;
减少锁竞争。
引入逻辑时钟偏移;
在NTP回拨时自动等待。
支持分布式部署管理
可将 machineId/datacenterId 从配置中心自动分配;
结合 ZooKeeper / etcd 动态注册节点ID。
持久化序列号
ID解码工具
结合数据库或缓存
在MySQL、Redis等系统中用作高效分布式主键。
793 阅读
865 阅读
21523 阅读
10489 阅读
9553 阅读
请填写红包祝福语或标题
红包个数最小为10个
红包金额最低5元
抵扣说明:
1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。 2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。