Snowflake 分布式id生成器--生成唯一ID

在 Snowflake 算法中,通常包含以下几个部分来构造一个唯一的 ID:

  1. 时间戳(Timestamp):占据了 64 位 ID 中的高 41 位,用来表示生成 ID 的时间。通过时间戳的递增,保证了生成的 ID 是递增且唯一的。

  2. 数据中心 ID(Data Center ID):用于标识不同的数据中心,通常占据了 5 位。

  3. 机器 ID(Worker ID):用于标识同一数据中心下的不同机器,也通常占据了 5 位。

  4. 序列号(Sequence Number):用来保证同一毫秒内生成的多个 ID 的唯一性,通常占据了 12 位。

Snowflake 算法的构造一般是这样的:

  1. 初始化:传入数据中心 ID 和机器 ID,初始化 Snowflake 实例时会生成一个开始时间戳(通常是指定一个固定的起始时间)。

  2. 生成 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。

posted @ 2024-03-20 19:22  He_LiangLiang  阅读(87)  评论(0编辑  收藏  举报