学习笔记9:雪花算法
雪花算法
雪花算法(Snowflake Algorithm)是一种生成唯一ID的算法,最初由Twitter开发。它的主要特点是生成的ID是64位的长整型数字,具有以下特性:
- 唯一性:每个生成的ID都是唯一的。
- 趋势递增:生成的ID是递增的,可以作为时间戳使用。
- 去中心化:可以在多个节点上生成ID,而不需要集中式协调。
雪花算法的基本结构
雪花算法生成的ID由以下几部分组成:
- 1位:未使用,始终为0。
- 41位:时间戳(毫秒级),表示从某个特定时间点(如2010年)开始的时间。
- 10位:机器ID,用于区分不同的机器或服务实例。
- 12位:序列号,用于同一毫秒内生成多个ID。
雪花算法的C++实现
以下是一个简化版的C++实现示例:
#include <iostream>
#include <chrono>
#include <cstdint>
#include <cstring>
class Snowflake {
private:
static const int64_t EPOCH = 1288834974657L; // 起始时间点,Twitter的起始时间点是2010-11-04
static const int64_t WORKER_ID_BITS = 10; // 机器ID所占位数
static const int64_t MAX_WORKER_ID = -1L ^ (-1L << WORKER_ID_BITS); // 机器ID最大值
static const int64_t SEQUENCE_BITS = 12; // 序列号所占位数
static const int64_t SEQUENCE_MASK = -1L ^ (-1L << SEQUENCE_BITS); // 序列号掩码
static const int64_t WORKER_ID_SHIFT = SEQUENCE_BITS; // 机器ID左移位数
static const int64_t TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS; // 时间戳左移位数
static const int64_t MAX_SEQUENCE = (1 << SEQUENCE_BITS) - 1; // 序列号最大值
static const int64_t TWEPOCH = 687888001L; // 以Twitter的起始时间点为例
int64_t workerId; // 机器ID
int64_t sequence; // 序列号
int64_t lastTimestamp; // 上次生成ID的时间戳
public:
Snowflake(int64_t workerId) : workerId(workerId), sequence(0), lastTimestamp(-1) {
if (workerId > MAX_WORKER_ID || workerId < 0) {
throw std::invalid_argument("Worker ID must be between 0 and 1023");
}
}
int64_t nextId() {
int64_t timestamp = timeGen();
if (timestamp < lastTimestamp) {
throw std::runtime_error("Clock moved backwards. Refusing to generate id for this time.");
}
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & MAX_SEQUENCE;
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0;
}
lastTimestamp = timestamp;
return ((timestamp - EPOCH) << TIMESTAMP_LEFT_SHIFT) |
(workerId << WORKER_ID_SHIFT) |
sequence;
}
private:
int64_t tilNextMillis(int64_t lastTimestamp) {
int64_t timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
int64_t timeGen() {
return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()
).count() + TWEPOCH;
}
};
int main() {
Snowflake snowflake(1); // 假设机器ID为1
for (int i = 0; i < 10; ++i) {
std::cout << "ID: " << snowflake.nextId() << std::endl;
}
return 0;
}
说明
- 时间戳:使用
std::chrono
库获取当前时间戳,并加上一个起始时间点(Twitter的起始时间点是2010-11-04)。 - 机器ID:在构造函数中传入,用于区分不同的机器或服务实例。
- 序列号:每次生成ID时递增,同一毫秒内最多生成4096个ID(2^12)。
- ID生成:通过按位运算组合时间戳、机器ID和序列号生成最终的ID。
这个实现是线程安全的,每次调用nextId
方法会生成一个新的ID。注意,这个实现依赖于系统时钟,如果系统时钟回拨,可能会导致生成重复的ID。
原文地址:https://blog.csdn.net/qq_29111047/article/details/140673915
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!