C語言實現分散式自增有序的唯一ID生成演算法-snowflake演算法
阿新 • • 發佈:2019-01-22
轉自:http://blog.csdn.net/wallwind/article/details/49701397
之前有人問我設計一個分散式的遞增的唯一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();
- #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