从零实现一个分布式ID生成器:雪花算法与号段模式

📅 2026/7/11 9:34:57
从零实现一个分布式ID生成器:雪花算法与号段模式
前言你有没有想过在分布式系统中订单ID、用户ID、消息ID是怎么生成的为什么它们能保证全局唯一且趋势递增分布式ID生成器是微服务架构的基础组件。今天我们从零实现两种分布式ID生成器· 雪花算法Snowflake—— 高性能、趋势递增· 号段模式Segment—— 批量获取、高可用---一、分布式ID的核心要求要求 说明全局唯一 所有服务生成的ID不重复趋势递增 ID按时间有序利于数据库索引高性能 单机每秒生成百万级ID高可用 不依赖单一节点可反解 从ID能解析出生成时间等信息---二、完整代码实现1. 雪花算法c#include stdio.h#include stdlib.h#include string.h#include unistd.h#include pthread.h#include time.h#include stdint.h// 雪花算法配置typedef struct snowflake_config {int worker_id_bits; // 机器ID位数默认5int datacenter_id_bits; // 数据中心ID位数默认5int sequence_bits; // 序列号位数默认12uint64_t worker_id;uint64_t datacenter_id;uint64_t epoch; // 起始时间戳毫秒} snowflake_config_t;// 雪花算法生成器typedef struct snowflake_generator {snowflake_config_t config;uint64_t last_timestamp;uint64_t sequence;uint64_t max_sequence;uint64_t worker_id_shift;uint64_t datacenter_id_shift;uint64_t timestamp_shift;uint64_t twepoch;pthread_mutex_t mutex;} snowflake_generator_t;// 创建雪花算法生成器snowflake_generator_t *snowflake_create(uint64_t worker_id, uint64_t datacenter_id) {snowflake_generator_t *gen malloc(sizeof(snowflake_generator_t));memset(gen, 0, sizeof(snowflake_generator_t));gen-config.worker_id_bits 5;gen-config.datacenter_id_bits 5;gen-config.sequence_bits 12;gen-config.worker_id worker_id ((1 5) - 1);gen-config.datacenter_id datacenter_id ((1 5) - 1);gen-config.epoch 1288834974657ULL;gen-max_sequence (1 gen-config.sequence_bits) - 1;gen-worker_id_shift gen-config.sequence_bits;gen-datacenter_id_shift gen-config.sequence_bits gen-config.worker_id_bits;gen-timestamp_shift gen-config.sequence_bits gen-config.worker_id_bits gen-config.datacenter_id_bits;gen-twepoch gen-config.epoch;gen-last_timestamp 0;gen-sequence 0;pthread_mutex_init(gen-mutex, NULL);return gen;}// 获取当前时间戳毫秒uint64_t get_timestamp_ms(void) {struct timeval tv;gettimeofday(tv, NULL);return (uint64_t)tv.tv_sec * 1000 tv.tv_usec / 1000;}// 等待下一个毫秒uint64_t wait_next_millis(uint64_t last_timestamp) {uint64_t ts get_timestamp_ms();while (ts last_timestamp) {ts get_timestamp_ms();usleep(100);}return ts;}// 生成IDuint64_t snowflake_next_id(snowflake_generator_t *gen) {pthread_mutex_lock(gen-mutex);uint64_t timestamp get_timestamp_ms();// 时钟回拨处理if (timestamp gen-last_timestamp) {int64_t diff gen-last_timestamp - timestamp;if (diff 5) {usleep(diff * 1000);timestamp get_timestamp_ms();} else {pthread_mutex_unlock(gen-mutex);return 0;}}if (timestamp gen-last_timestamp) {gen-sequence (gen-sequence 1) gen-max_sequence;if (gen-sequence 0) {timestamp wait_next_millis(gen-last_timestamp);}} else {gen-sequence 0;}gen-last_timestamp timestamp;uint64_t id ((timestamp - gen-twepoch) gen-timestamp_shift) |(gen-config.datacenter_id gen-datacenter_id_shift) |(gen-config.worker_id gen-worker_id_shift) |gen-sequence;pthread_mutex_unlock(gen-mutex);return id;}// 解析IDvoid snowflake_parse_id(uint64_t id, snowflake_config_t *config,uint64_t *timestamp, uint64_t *datacenter_id,uint64_t *worker_id, uint64_t *sequence) {uint64_t timestamp_shift config-sequence_bits config-worker_id_bits config-datacenter_id_bits;*timestamp (id timestamp_shift) config-epoch;*datacenter_id (id (config-sequence_bits config-worker_id_bits)) ((1 config-datacenter_id_bits) - 1);*worker_id (id config-sequence_bits) ((1 config-worker_id_bits) - 1);*sequence id ((1 config-sequence_bits) - 1);}2. 号段模式c// 号段生成器typedef struct segment_generator {char biz_tag[64];uint64_t max_id;uint64_t step;uint64_t current_id;uint64_t segment_start;uint64_t segment_end;int initialized;pthread_mutex_t mutex;struct segment_generator *next;} segment_generator_t;// 号段管理器typedef struct segment_manager {segment_generator_t *generators;pthread_mutex_t mutex;} segment_manager_t;segment_manager_t *g_segment_manager NULL;// 创建号段管理器segment_manager_t *segment_manager_create(void) {segment_manager_t *sm malloc(sizeof(segment_manager_t));sm-generators NULL;pthread_mutex_init(sm-mutex, NULL);return sm;}// 加载或创建号段segment_generator_t *segment_load_or_create(segment_manager_t *sm,const char *biz_tag, uint64_t step) {pthread_mutex_lock(sm-mutex);segment_generator_t *gen sm-generators;while (gen) {if (strcmp(gen-biz_tag, biz_tag) 0) {pthread_mutex_unlock(sm-mutex);return gen;}gen gen-next;}gen malloc(sizeof(segment_generator_t));memset(gen, 0, sizeof(segment_generator_t));strcpy(gen-biz_tag, biz_tag);gen-step step;gen-current_id 0;gen-initialized 0;pthread_mutex_init(gen-mutex, NULL);gen-next sm-generators;sm-generators gen;pthread_mutex_unlock(sm-mutex);return gen;}// 获取下一段号段void segment_fetch_next(segment_generator_t *gen) {pthread_mutex_lock(gen-mutex);if (!gen-initialized) {gen-max_id 0;gen-initialized 1;}gen-segment_start gen-max_id 1;gen-segment_end gen-max_id gen-step;gen-max_id gen-segment_end;gen-current_id gen-segment_start - 1;printf([Segment] 分配号段: %s [%llu, %llu]\n,gen-biz_tag, gen-segment_start, gen-segment_end);pthread_mutex_unlock(gen-mutex);}// 获取下一个IDuint64_t segment_next_id(segment_generator_t *gen) {pthread_mutex_lock(gen-mutex);if (!gen-initialized || gen-current_id gen-segment_end) {pthread_mutex_unlock(gen-mutex);segment_fetch_next(gen);pthread_mutex_lock(gen-mutex);}uint64_t id gen-current_id;pthread_mutex_unlock(gen-mutex);return id;}3. 混合生成器c// 混合生成器typedef struct hybrid_generator {snowflake_generator_t *snowflake;segment_generator_t *segment;int mode;} hybrid_generator_t;hybrid_generator_t *hybrid_create(uint64_t worker_id, uint64_t datacenter_id,const char *biz_tag, uint64_t step) {hybrid_generator_t *hybrid malloc(sizeof(hybrid_generator_t));hybrid-snowflake snowflake_create(worker_id, datacenter_id);hybrid-segment segment_load_or_create(g_segment_manager, biz_tag, step);hybrid-mode 0;return hybrid;}uint64_t hybrid_next_id(hybrid_generator_t *hybrid) {if (hybrid-mode 0) {return snowflake_next_id(hybrid-snowflake);} else {return segment_next_id(hybrid-segment);}}4. 测试代码cvoid test_snowflake() {printf( 雪花算法测试 \n\n);snowflake_generator_t *gen snowflake_create(1, 1);printf(生成10个ID:\n);for (int i 0; i 10; i) {uint64_t id snowflake_next_id(gen);printf( %llu\n, id);uint64_t ts, dc, worker, seq;snowflake_parse_id(id, gen-config, ts, dc, worker, seq);printf( - 时间:%llu, 数据中心:%llu, 机器:%llu, 序列:%llu\n,ts, dc, worker, seq);}free(gen);}void test_segment() {printf(\n 号段模式测试 \n\n);segment_manager_t *sm segment_manager_create();g_segment_manager sm;segment_generator_t *gen segment_load_or_create(sm, order, 100);segment_fetch_next(gen);printf(生成20个ID:\n);for (int i 0; i 20; i) {printf( %llu\n, segment_next_id(gen));}free(sm);}void test_performance() {printf(\n 性能测试 \n);snowflake_generator_t *gen snowflake_create(1, 1);int count 1000000;clock_t start clock();for (int i 0; i count; i) {snowflake_next_id(gen);}clock_t end clock();double elapsed (double)(end - start) / CLOCKS_PER_SEC;printf(生成 %d 个ID, 耗时 %.3f 秒\n, count, elapsed);printf(QPS: %.0f\n, count / elapsed);free(gen);}int main() {test_snowflake();test_segment();test_performance();return 0;}---三、编译和运行bashgcc -o id_generator id_generator.c -lpthread./id_generator---四、两种算法对比特性 雪花算法 号段模式ID类型 64位整数 64位整数性能 极高 高依赖 时钟同步 持久化存储有序性 趋势递增 连续递增可反解 ✅ ❌适用场景 高并发 数据库主键---五、总结通过这篇文章你学会了· 分布式ID的核心要求· 雪花算法的结构时间戳机器ID序列号· 号段模式的批量获取· 两种算法的适用场景分布式ID生成器是微服务架构的基础组件。掌握它你就理解了订单号、流水号等业务ID的设计原理。下一篇预告《从零实现一个分布式限流器令牌桶与漏桶》---评论区分享一下你用过什么分布式ID方案