在 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。