转自:http://blog.csdn.net/wallwind/article/details/49701397
之前有人问我设计一个分布式的递增的唯一id生成。想了半天不知道,偶然一个同事说起snowflake算法,我百度了一下,很简单高效。
参考
https://github.com/twitter/snowflake
于是,我自己用c语言随便实现了一下,还没有达到工业级别,需要细化,但是基本能用了,上代码。
-
-
-
-
-
-
-
-
-
-
-
-
-
- #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