zoukankan      html  css  js  c++  java
  • C语言版的twitter分布式全局唯一标识snowflake Id

    snowflake.h

    /**
     * snowflake.h
     *
     * nextId()
     * 
     * nextIdFrom(unsigned char datacenterId, unsigned char workerId)
     *
     **/
    
    #include <stdint.h>
    
    // 定义起始的日期时间戳
    #define EPOCH 1584340752713ULL
    
    // 获取默认id
    uint64_t nextId(void);
    
    // 从指定的数据中心的指定的工作站获取id
    uint64_t nextIdFrom(unsigned char, unsigned char);

    snowflake.c

    /**
     * filename: snowflake.c
     *
     * date: 2020-2-20 20:20:02
     *
     * description: 分布式全局唯一标识,
     *         Twitter的Snowflake算法的c语言实现(单线程)。
     *
     **/
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <sys/timeb.h>
    #include "snowflake.h"
    
    // 默认的数据中心标识
    const unsigned char DEFAULT_DATACENTER_ID = 0;
    
    // 默认的工作站标识
    const unsigned char DEFAULT_WORKER_ID = 0;
    
    uint64_t BASE_TIMESTAMP_MILLISEC = EPOCH;    //EPOCH在snowflake.h中定义
    uint64_t last_timestamp_millisec = 0;
    uint64_t current_timestamp_millisec = 0;
    
    unsigned short squenceNumber = 0;
    
    // 
    _Bool invalidWorkerId(const unsigned char, const unsigned char);
    
    // 当前毫秒时间戳
    void setCurrentTimeStampMillis(uint64_t *);
    
    
    uint64_t nextId(void)
    {
        return nextIdFrom(DEFAULT_DATACENTER_ID, DEFAULT_WORKER_ID);
    }
    
    uint64_t nextIdFrom(unsigned char datacenterId, unsigned char workerId)
    {
    
        invalidWorkerId(datacenterId, workerId);
        //datacenterId &= 0x1F;
        //workerId &= 0x1F;
    
        setCurrentTimeStampMillis(&current_timestamp_millisec);
        if (squenceNumber >= 0xfff)
        {
            squenceNumber = 0;
            do
            {
                setCurrentTimeStampMillis(&current_timestamp_millisec);
            } while (current_timestamp_millisec <= last_timestamp_millisec);
            
            last_timestamp_millisec = current_timestamp_millisec;
        }
    
        uint64_t timeStamp = current_timestamp_millisec - BASE_TIMESTAMP_MILLISEC;
        
        uint64_t id = (timeStamp << 22) 
            | (datacenterId << 17)
            | (workerId << 12)
            | squenceNumber++ & 0xfff;
        
        return id;
    }
    
    _Bool invalidWorkerId(const unsigned char datacenterId, const unsigned char workerId)
    {
        if (datacenterId >= 32 || workerId >= 32){
            fprintf(stderr, "[nextIdFrom() @ snowflake.c] "
                    "ERROR! datacenterId and workerId both "
                    "must be unsigned integer between 0 to 31, "
                    "application exit!
    ");
            exit(-1);    // other way: return 0 here;
        }
        return 1;
    }
    
    
    void setCurrentTimeStampMillis(uint64_t * millisec)
    {
        struct timeb stCurrentTimeStamp;
        ftime(&stCurrentTimeStamp);
        (*millisec) = (uint64_t)stCurrentTimeStamp.time * 1000 + (uint64_t)stCurrentTimeStamp.millitm;
    }

    main.c

    #include <stdio.h>
    #include "snowflake.h"
    
    int main(void)
    {
        for (int i = 0; i < 600; i++)
        {
            printf("id[%4d]=%20I64u
    ", i + 1, nextId() );
        }
        return 0;
    }
  • 相关阅读:
    windows2012 永激活及配置
    Fiddler2 英文版翻译
    你知道using的用法吗?
    你会利用css写下拉列表框吗?
    完美解决.net2.0和.net4.0在同一个iis中共同运行
    深入剖析new override和virtual关键字
    思科防火墙,h3c三层交换机配置笔记
    c# 笔记 数据类型转换 数组 函数
    Silverlight 完美征程 笔记1 (控件模型)
    C#笔记(流程控制)
  • 原文地址:https://www.cnblogs.com/godwithus/p/12609830.html
Copyright © 2011-2022 走看看