在 Snowflake 算法中,通常包含以下几个部分来构造一个唯一的 ID:
-
时间戳(Timestamp):占据了 64 位 ID 中的高 41 位,用来表示生成 ID 的时间。通过时间戳的递增,保证了生成的 ID 是递增且唯一的。
-
数据中心 ID(Data Center ID):用于标识不同的数据中心,通常占据了 5 位。
-
机器 ID(Worker ID):用于标识同一数据中心下的不同机器,也通常占据了 5 位。
-
序列号(Sequence Number):用来保证同一毫秒内生成的多个 ID 的唯一性,通常占据了 12 位。
Snowflake 算法的构造一般是这样的:
-
初始化:传入数据中心 ID 和机器 ID,初始化 Snowflake 实例时会生成一个开始时间戳(通常是指定一个固定的起始时间)。
-
生成 ID:在生成 ID 的时候,根据当前时间戳、数据中心 ID、机器 ID 和序列号生成一个 64 位的唯一 ID。
在 C++ 中,你可以定义一个 Snowflake 类,包含合适的成员变量和方法,以实现 Snowflake 算法。以下是一个简单的示例:
#include <iostream> #include <chrono> #include <thread> class Snowflake { private: int dataCenterId; int workerId; long long sequence; long long lastTimestamp; public: Snowflake(int dataCenterId, int workerId) : dataCenterId(dataCenterId), workerId(workerId), sequence(0), lastTimestamp(-1) {} long long generateId() { long long timestamp = getCurrentTimestamp(); if (timestamp < lastTimestamp) { // 时间回退,抛出异常或者等待直到时间追上 throw std::runtime_error("Clock moved backwards. Refusing to generate id."); } if (timestamp == lastTimestamp) { sequence = (sequence + 1) & 0xFFF; // 序列号取值范围为0~4095 if (sequence == 0) { timestamp = waitNextMillis(lastTimestamp); } } else { sequence = 0; } lastTimestamp = timestamp; return ((timestamp - 1609459200000) << 22) | (dataCenterId << 17) | (workerId << 12) | sequence; } private: long long getCurrentTimestamp() { return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); } long long waitNextMillis(long long lastTimestamp) { long long timestamp = getCurrentTimestamp(); while (timestamp <= lastTimestamp) { timestamp = getCurrentTimestamp(); } return timestamp; } }; int main() { Snowflake snowflake(1, 1); // 数据中心ID为1,机器ID为1 for(int i=0;i<100;i++){ long long uniqueId = snowflake.generateId(); std::cout << "Generated unique ID: " << uniqueId << std::endl<<std::flush; } return 0; }
在这个示例中,generateId
方法根据当前时间戳、数据中心 ID、机器 ID 和序列号生成唯一的 ID。getCurrentTimestamp
方法获取当前的毫秒级时间戳,waitNextMillis
方法用来等待直到时间追上。整个 Snowflake 类实现了一个简单的 Snowflake 算法生成唯一 ID。