snowflake changes from global static variables to one instance per thread

This commit is contained in:
luwenpeng
2024-08-23 15:21:07 +08:00
parent 3014e0feef
commit 6808e6ba29
30 changed files with 420 additions and 167 deletions

View File

@@ -1,57 +1,61 @@
#include <time.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include "log.h"
#include "utils.h"
#include "stellar.h"
#include "snowflake.h"
#define snowflake_LOG_ERROR(format, ...) LOG_ERROR("snowflake", format, ##__VA_ARGS__)
#define snowflake_LOG_DEBUG(format, ...) LOG_DEBUG("snowflake", format, ##__VA_ARGS__)
#define SNOWFLAKE_LOG_ERROR(format, ...) LOG_ERROR("snowflake", format, ##__VA_ARGS__)
struct snowflake
{
uint8_t snowflake_base; // 5bit [0, 31]
uint8_t snowflake_offset; // 7bit [0, 127]
uint64_t device_id; // 12bit [0, 4095] ( base << 7 | offset )
uint64_t thread[MAX_THREAD_NUM];
uint8_t worker_base_id; // 5 bit [0, 31]
uint8_t worker_offset_id; // 7 bit [0, 127]
uint64_t thread_id; // limit 256
uint64_t device_id; // 12 bit [0, 4095] ( base << 7 | offset )
uint64_t sequence;
};
struct snowflake g_snowflake = {};
// return 0: success
// return -1: failed
int snowflake_id_init(const struct snowflake_options *opts)
struct snowflake *snowflake_new(uint16_t thread_id, uint8_t worker_base_id, uint8_t worker_offset_id)
{
memset(&g_snowflake, 0, sizeof(struct snowflake));
if (opts == NULL)
if (thread_id > 255)
{
snowflake_LOG_ERROR("opts is NULL");
return -1;
SNOWFLAKE_LOG_ERROR("thread_id %u is invalid, range [0, 255]", thread_id);
return NULL;
}
if (worker_base_id > 31)
{
SNOWFLAKE_LOG_ERROR("worker_base_id %u is invalid, range [0, 31]", worker_base_id);
return NULL;
}
if (worker_offset_id > 127)
{
SNOWFLAKE_LOG_ERROR("worker_offset_id %u is invalid, range [0, 127]", worker_offset_id);
return NULL;
}
if (opts->snowflake_base > 31)
struct snowflake *sf = (struct snowflake *)calloc(1, sizeof(struct snowflake));
if (sf == NULL)
{
snowflake_LOG_ERROR("snowflake_base %u is invalid, range [0, 31]", opts->snowflake_base);
return -1;
SNOWFLAKE_LOG_ERROR("calloc snowflake failed");
return NULL;
}
if (opts->snowflake_offset > 127)
sf->worker_base_id = worker_base_id;
sf->worker_offset_id = worker_offset_id;
sf->thread_id = thread_id;
sf->device_id = ((worker_base_id << 7) | worker_offset_id) & 0xFFF;
sf->sequence = 0;
return sf;
}
void snowflake_free(struct snowflake *sf)
{
if (sf != NULL)
{
snowflake_LOG_ERROR("snowflake_offset %u is invalid, range [0, 127]", opts->snowflake_offset);
return -1;
free(sf);
sf = NULL;
}
g_snowflake.snowflake_base = opts->snowflake_base;
g_snowflake.snowflake_offset = opts->snowflake_offset;
g_snowflake.device_id = ((g_snowflake.snowflake_base << 7) | g_snowflake.snowflake_offset) & 0xFFF;
snowflake_LOG_DEBUG("snowflake_base: %u, snowflake_offset: %u, device_id: %u",
g_snowflake.snowflake_base,
g_snowflake.snowflake_offset,
g_snowflake.device_id);
return 0;
}
/*
@@ -61,20 +65,41 @@ int snowflake_id_init(const struct snowflake_options *opts)
* | 1bit | 12bit device_id | 8bit thread_id | 28bit timestamp in sec | 15bit sequence per thread |
* +------+------------------+----------------+------------------------+---------------------------+
*/
uint64_t snowflake_id_generate(uint64_t now_sec)
{
#define MAX_ID_PER_THREAD (32768)
#define MAX_ID_BASE_TIME (268435456L)
uint64_t thr_idx = (uint16_t)stellar_get_current_thread_index();
uint64_t snowflake_generate(struct snowflake *sf, uint64_t now_sec)
{
if (sf == NULL)
{
SNOWFLAKE_LOG_ERROR("snowflake is NULL");
return 0;
}
uint64_t global_id = 0;
uint64_t id_per_thread = (g_snowflake.thread[thr_idx]++) % MAX_ID_PER_THREAD;
uint64_t id = 0;
uint64_t id_per_thread = (sf->sequence++) % MAX_ID_PER_THREAD;
uint64_t id_base_time = now_sec % MAX_ID_BASE_TIME;
global_id = (g_snowflake.device_id << 51) |
(thr_idx << 43) |
(id_base_time << 15) |
(id_per_thread);
id = (sf->device_id << 51) |
(sf->thread_id << 43) |
(id_base_time << 15) |
(id_per_thread);
return global_id;
return id;
}
void snowflake_deserialize(uint64_t id, struct snowflake_meta *meta)
{
if (meta == NULL)
{
return;
}
meta->sequence = id & 0x7FFF;
meta->time_cycle = MAX_ID_BASE_TIME;
meta->time_relative = (id >> 15) & 0xFFFFFFF;
meta->thread_id = (id >> 43) & 0xFF;
meta->device_id = (id >> 51) & 0xFFF;
meta->worker_base_id = (meta->device_id >> 7) & 0x1F;
meta->worker_offset_id = meta->device_id & 0x7F;
}