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

#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
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值