facebook-雪花算法-分布式ID-C++实现

2022-02-25 09:08:53 浏览数 (1)

代码语言:javascript复制
#include <stdint.h>
#include <sys/time.h>
#include <stdexcept>
#include <mutex>
#include <thread>
#include "lightlog.h"

class SnowFlake {
private:
	static const uint64_t m_start_time_stamp = 1480166465631; // 初始时间戳 给一个随机值
	static const uint64_t m_sequence_bit = 12;
	static const uint64_t m_machine_bit = 5;
	static const uint64_t m_datacenter_bit = 5;
	
	// 获取位数的最大值
	static const uint64_t m_max_datacenter_num = -1 ^ (uint64_t(-1) << m_datacenter_bit);
	static const uint64_t m_max_machine_num = -1 ^ (uint64_t(-1) << m_machine_bit);
	static const uint64_t m_max_sequence_num = -1 ^ (uint64_t(-1) << m_sequence_bit);
	
	// 下标
	static const uint64_t m_machine_left = m_sequence_bit;
	static const uint64_t m_datacenter_left = m_sequence_bit   m_machine_bit;
	static const uint64_t m_timestamp_left = m_sequence_bit   m_machine_bit   m_datacenter_bit;
	
	
	uint64_t m_datacenterId;
	uint64_t m_machineId;
	uint64_t m_sequence;
	uint64_t m_last_time_stamp;
	
	std::mutex m_mtx;
	
	uint64_t GetNextMill() {
		uint64_t mill = GetNewTimeStamp();
		while (mill <= m_last_time_stamp) {
			mill = GetNewTimeStamp();
		}
		return mill;
	}
	
	uint64_t GetNewTimeStamp() {
		struct timeval tv;
		gettimeofday(&tv, NULL);
		uint64_t time = tv.tv_sec;
		time /= 1000;
		time  = (tv.tv_sec * 1000);
		return time;	
	}
public:
	SnowFlake(int datacenterId, int machineId)
	{
		// 参数校验
		if ((uint64_t)datacenterId > m_max_datacenter_num || (uint64_t)datacenterId < 0) {
			LLOG(ERRO) << "datacenterId can't be greater than max_datacenter_num_ or less than 0";
			exit(0);
		}
		
		if ((uint64_t)machineId > m_max_machine_num || (uint64_t)machineId < 0) {
			LLOG(ERRO) << "machineId can't be greater than max_machine_num_or less than 0";
			exit(0);
		}
		m_datacenterId = datacenterId;
		m_machineId = machineId;
		m_sequence = 0L;
		m_last_time_stamp = 0L;
	}
	
	
	uint64_t NextId() {
		std::unique_lock<std::mutex> lock(m_mtx);
		uint64_t curTimeStamp = GetNewTimeStamp();
		if (curTimeStamp < m_last_time_stamp) {
			LLOG(ERRO) << "clock moved backwards. refusing to generate id";
			exit(0);
		}
		
		if (curTimeStamp == m_last_time_stamp) {
			m_sequence = (m_sequence   1) & m_max_sequence_num;
			if (m_sequence == 0) {
				curTimeStamp = GetNextMill();
			}
		} else {
			m_sequence = 0;
		}
		
		m_last_time_stamp = curTimeStamp;
		return (curTimeStamp - m_start_time_stamp) << m_timestamp_left
			| m_datacenterId << m_datacenter_left
			| m_machineId << m_machine_left
			| m_sequence;
	}
};


void func(void* arg) {
	SnowFlake* sf = (SnowFlake*)arg;
	for (int i = 0; i < 10; i  ) {
		LLOG(INFO) << sf->NextId();
	}
	return;
}


int main() {
	SnowFlake sf(2, 3);
	std::thread t1(func, &sf);
	t1.join();
	return 0;
}

我的博客即将同步至腾讯云 社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=1jaldbd5jadaj

0 人点赞