C语言实现分布式自增有序的唯一ID生成算法-snowflake算法
2015-11-07 13:28
656 查看
之前有人问我设计一个分布式的递增的唯一id生成。想了半天不知道,偶然一个同事说起snowflake算法,我百度了一下,很简单高效。
参考
https://github.com/twitter/snowflake
于是,我自己用c语言随便实现了一下,还没有达到工业级别,需要细化,但是基本能用了,上代码。
/*
snowflake
ID 生成策略
毫秒级时间41位+机器ID 10位+毫秒内序列12位。
0 41 51 64 +-----------+------+------+ |time |pc |inc | +-----------+------+------+
前41bits是以微秒为单位的timestamp。
接着10bits是事先配置好的机器ID。
最后12bits是累加计数器。
macheine id(10bits)标明最多只能有1024台机器同时产生ID,sequence number(12bits)也标明1台机器1ms中最多产生4096个ID, *
注意点,因为使用到位移运算,所以需要64位操作系统,不然生成的ID会有可能不正确
*/
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <sched.h>
#include <linux/unistd.h>
#include <sys/syscall.h>
#include <errno.h>
#include<linux/types.h>
#include<time.h>
#include <stdint.h>
#include <sys/time.h>
struct globle
{
int global_int:12;
uint64_t last_stamp;
int workid;
int seqid;
};
void set_workid(int workid);
pid_t gettid( void );
uint64_t get_curr_ms();
uint64_t wait_next_ms(uint64_t lastStamp);
int atomic_incr(int id);
uint64_t get_unique_id();
支持原子自增操作。
多线程情况下,可以将workid进行移位加上线程ID。
更多文章欢迎访问:http://blog.csdn.net/wallwind
参考
https://github.com/twitter/snowflake
于是,我自己用c语言随便实现了一下,还没有达到工业级别,需要细化,但是基本能用了,上代码。
/*
snowflake
ID 生成策略
毫秒级时间41位+机器ID 10位+毫秒内序列12位。
0 41 51 64 +-----------+------+------+ |time |pc |inc | +-----------+------+------+
前41bits是以微秒为单位的timestamp。
接着10bits是事先配置好的机器ID。
最后12bits是累加计数器。
macheine id(10bits)标明最多只能有1024台机器同时产生ID,sequence number(12bits)也标明1台机器1ms中最多产生4096个ID, *
注意点,因为使用到位移运算,所以需要64位操作系统,不然生成的ID会有可能不正确
*/
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <sched.h>
#include <linux/unistd.h>
#include <sys/syscall.h>
#include <errno.h>
#include<linux/types.h>
#include<time.h>
#include <stdint.h>
#include <sys/time.h>
struct globle
{
int global_int:12;
uint64_t last_stamp;
int workid;
int seqid;
};
void set_workid(int workid);
pid_t gettid( void );
uint64_t get_curr_ms();
uint64_t wait_next_ms(uint64_t lastStamp);
int atomic_incr(int id);
uint64_t get_unique_id();
#include "snowflake.h" struct globle g_info; #define sequenceMask (-1L ^ (-1L << 12L)) void set_workid(int workid) { g_info.workid = workid; } pid_t gettid( void ) { return syscall( __NR_gettid ); } uint64_t get_curr_ms() { struct timeval time_now; gettimeofday(&time_now,NULL); uint64_t ms_time =time_now.tv_sec*1000+time_now.tv_usec/1000; return ms_time; } uint64_t wait_next_ms(uint64_t lastStamp) { uint64_t cur = 0; do { cur = get_curr_ms(); } while (cur <= lastStamp); return cur; } int atomic_incr(int id) { __sync_add_and_fetch( &id, 1 ); return id; } uint64_t get_unique_id() { uint64_t uniqueId=0; uint64_t nowtime = get_curr_ms(); uniqueId = nowtime<<22; uniqueId |=(g_info.workid&0x3ff)<<12; if (nowtime <g_info.last_stamp) { perror("error"); exit(-1); } if (nowtime == g_info.last_stamp) { g_info.seqid = atomic_incr(g_info.seqid)& sequenceMask; if (g_info.seqid ==0) { nowtime = wait_next_ms(g_info.last_stamp); } } else { g_info.seqid = 0; } g_info.last_stamp = nowtime; uniqueId |=g_info.seqid; return uniqueId; } int main() { set_workid(100); int size; for (;;) { uint64_t unquie = get_unique_id(); printf("pthread_id:%u, id [%llu]\n",gettid(),unquie); } return; }
支持原子自增操作。
多线程情况下,可以将workid进行移位加上线程ID。
更多文章欢迎访问:http://blog.csdn.net/wallwind
相关文章推荐
- 关于C++的STL学习
- C语言/单片机基础训练之红绿灯
- 转换字符串格式为原来字符串里字符+该字符连续出现的个数
- 今日学习札记——C语言指针与程序风格(11.6)
- 对于C语言中数组名是指针的理解
- 一起talk C栗子吧(第五十九回:C语言实例--字符串概述)
- 简单c语言小游戏实现原理
- C++ Primer 学习笔记_33_STL实践与分析(7) --容器适配器
- 简单工厂模式
- C++中的get,gets,getline
- C++ learning notes - const
- C++基础知识---static const初始化成员变量
- C++基础——对函数模板的类型推导的补充
- C++基础——模板的0初始化
- 排序算法(三):简单选择排序
- 如何两个模板类会相互包含,那么需要在类定义之前声明其中一个类,并且声明时要用模板。
- c++: size_type与 size_t
- C++的机器学习开源库
- C++特征之多态
- 值得学习的C C++语言开源项目