• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

C语言版的twitter分布式全局唯一标识snowflakeId

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

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!\n");
        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\n", i + 1, nextId() );
    }
    return 0;
}

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
public,private,protected访问权限在Java,C++中的解析发布时间:2022-07-13
下一篇:
C++函数返回值传递发布时间:2022-07-13
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap