设计背景
用作游戏服务器给每个角色生成UID,给物品生成唯一ID,有多个服务器类型,例如:游戏服,中心服,网关服等等;每个类型的服务器有多个,比如10个游戏服,20个网关服等
设计思想
1. 思路参考雪花算法,即多个字段拼接成一个64位的数字
2. 最高位不用,4位服务器类型,7位服务器ID,32位时间戳,20位自增ID
3. 服务器类型占4位,所以有2的4次方,即16种不同的服务器类型
4. 服务器ID占7位,所以有2的7次方,即同一类型的服务器最多可以有128个
5. 时间戳占32位,精确到秒
6. 自增ID占20位,即2的20次方,每秒最多产生1048576个唯一ID
备注
使用时可以根据实际情况修改各个字段的占位数
代码下载地址:
windows版: https://download.csdn.net/download/yzf279533105/11955287
运行结果如下图(实验时只产生了一次UID,并打印出来):
代码如下:
使用代码:
int main()
{
// 使用前先初始化
IDGenerate::getSingleton().Init(ST_GAME,1);
// 使用
uint64_t uid = IDGenerate::getSingleton().GenerateUID();
cout<<uid<<endl;
getchar();
return 0;
}
头文件
* All rights reserved.
* 文件名称: IDGenerate.h
* 作 者: yzf
* 摘 要: UID生成器
* 目前规则:1位保留 + 4位服务器类型 + 7位服务器ID + 32位时间戳 + 20位自增ID
* 每秒可以生产2的20次方,也就是1048576个UID
* 使用前需先初始化,否则返回0(也可以在GenerateUID()内部判断,若未初始化,则进行初始化,这样接口更少)
* 完成日期: 2019-11-3
********************************************************************/
#ifndef __ID_GENERATE_H__
#define __ID_GENERATE_H__
#include <stdio.h>
#include "define.h"
#include "singleton.h"
//////////////////////////////////////////////////////////////////////////
class IDGenerate : public Singleton<IDGenerate>
{
public:
IDGenerate();
virtual ~IDGenerate();
public:
// 生成一个全局唯一的UID
uint64_t GenerateUID();
/**
@purpose : 初始化
@param serverType : 服务器类型
@param serverID : 服务器ID
*/
void Init(SERVER_TYPE serverType, int serverID);
protected:
bool m_bInit; // 是否已初始化
SERVER_TYPE m_serverType; // 服务器类型
int m_serverID; // 服务器ID,同一类型的服务器中需唯一
int m_lastSecond; // 上次产生ID时的时间戳,单位:秒
int m_addID; // 自增ID
};
源文件
#include <time.h>
#include "IDGenerate.h"
//////////////////////////////////////////////////////////////////////////
IDGenerate::IDGenerate()
{
m_bInit = false;
m_addID = 0;
}
//////////////////////////////////////////////////////////////////////////
IDGenerate::~IDGenerate()
{
}
// 生成一个全局唯一的UID
uint64_t IDGenerate::GenerateUID()
{
if (!m_bInit)
{
printf("IDGenerate::GenerateUID(), m_bInit = false !!!!!");
return 0;
}
// 当前时间
unsigned int curSecond = time(NULL);
// 若秒数不同了,则自增ID重新从0开始
if(curSecond != m_lastSecond)
{
m_lastSecond = curSecond;
m_addID = 0;
}
return ((uint64_t)m_serverType<<59) + ((uint64_t)m_serverID<<52) + ((uint64_t)curSecond<<20) + ((uint64_t)m_addID++);
}
/**
@purpose : 初始化
@param serverType : 服务器类型
@param serverID : 服务器ID
*/
void IDGenerate::Init(SERVER_TYPE serverType, int serverID)
{
m_serverType = serverType;
m_serverID = serverID;
m_bInit = true;
}
SINGLETON_INIT(IDGenerate)