几年前写过C++版本并测试都没问题,见我以前的链接:http://blog.csdn.net/monster877/article/details/23067189
现在翻译成C#版本,创建10万个GUID的时间只需要3ms左右,C++的或许速度更快,具体算法如下:
1 using System;
3 using System.Collections.Generic;
4 using System.Diagnostics;
5 using System.Linq;
6 using System.Text;
7 using System.Threading.Tasks;
8
9 namespace Test
10 {
11
12 //自定义GUID
13 public class MyGuid
14 {
15 /**
16 本程序可以生成64位全游戏大世界全局唯一ID,适合在分布式服务器集群中产生唯一ID
17 特点比微软自带的GUID要节省一倍的空间,即只需要64位的int即可,因此基本上在游戏服务器领域可以抛弃微软的那个GUID了
18 支持每秒生成4096个,在此条件基础上这辈子都不会产生相同的ID
19
20 由 时间戳+服务器区号+平台号+本地递增序号 组成
21
22 时间戳 32bit
23 服务器区号 12bit
24 平台号 8bit
25 递增序号 12bit
26 */
27 private static ulong c_mark_time_stamp = 0xffffffff00000000;/*时间戳掩码*/
28 private static ulong c_mark_district = 0x00000000fff00000;/*服务器区号掩码*/
29 private static ulong c_mark_plat = 0x00000000000ff000;/*服务器里的平台号掩码*/
30 private static ulong c_mark_base = 0x0000000000000fff;/*本地ID编号掩码*/
31 private static uint c_baseId = 0;/*本地ID*/
32 private static readonly DateTime Jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
33
34 //生成整个世界里全局唯一的ID district:服务器区号,platform:平台号 [如果游戏只接一个平台,则此平台号可以是服务器集群里的服务器类型编号]
35 public static ulong NewGuid(uint platform, uint district)
36 {
37 ulong timeStamp = (ulong)(DateTime.UtcNow- Jan1st1970).TotalSeconds;//获取自古以来的时间戳
38 ulong newId = ((timeStamp << 32) & c_mark_time_stamp) | ((district << 20) & c_mark_district) | ((platform << 12) & c_mark_plat) | (c_baseId & c_mark_base);
39
40 c_baseId++;
41
42 return newId;
43 }
44 }
45 class Program
46 {
47 static void Main(string[] args)
48 {
49 ulong guid = MyGuid.NewGuid(1, 1);
50 }
51 }
52 }
有人嫌每秒只能4096个少了,可以改成这样就可以每秒100多万了:
public class MyGuid
{
/**
本程序可以生成64位全游戏大世界全局唯一ID,适合在分布式服务器集群中产生唯一ID
特点比微软自带的GUID要节省一倍的空间,即只需要64位的int即可,因此基本上在游戏服务器领域可以抛弃微软的那个GUID了
支持每秒生成1048576个,在此条件基础上这辈子都不会产生相同的ID
由 时间戳+大区号+小区号+本地递增序号 组成
时间戳 32bit
大区号 4bit
小区号 8bit
递增序号 20bit
支持大区16个,每个大区下支持256个小区,每个小区里支持每秒生成1048576个唯一ID
*/
private static ulong c_mark_time_stamp = 0xffffffff00000000;/*时间戳掩码*/
private static ulong c_mark_big_district = 0x00000000f0000000;/*大区号掩码*/
private static ulong c_mark_small_district = 0x000000000ff00000;/*小区号掩码*/
private static ulong c_mark_base = 0x00000000000fffff;/*本地ID编号掩码*/
private static uint c_baseId = 0;/*本地ID*/
private static readonly DateTime Jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public static ulong NewGuid(uint bigDistrict, uint smallDistrict)
{
ulong timeStamp = (ulong)(DateTime.UtcNow - Jan1st1970).TotalSeconds;//获取自古以来的时间戳
ulong newId = ((timeStamp << 32) & c_mark_time_stamp) | ((bigDistrict << 28) & c_mark_big_district) | ((smallDistrict << 20) & c_mark_small_district) | (c_baseId & c_mark_base);
c_baseId++;
return newId;
}
}
最后再贴一下适合大世界的版本,支持根据guid反推所在服务器信息哦
//服务器类型
public enum ServerType
{
DB = 1, //数据库服务器
Logic = 2, //逻辑服务器
World = 3, //世界服务器
AC = 4, //平台认证服务器
Proxy = 5, //网关服务器
Center = 6, //中心服务器
Record = 7, //记录服务器
}
//自定义GUID
public class MyGuid
{
/**
本程序可以生成64位全游戏大世界全局唯一ID,适合在分布式服务器集群中产生唯一ID,也适合分区分服的服务器,可自由更改掩码与占位调节
特点比微软自带的GUID要节省一倍的空间,即只需要64位的int即可,因此基本上在游戏服务器领域可以抛弃微软的那个GUID了
支持每秒生成65536个,在此条件基础上这辈子都不会产生相同的ID
由 时间戳+服务器类型号+服务器ID号+本地递增序号 组成
时间戳 32bit
服务器类型号 4bit [允许16种不同类型的服务器]
服务器编号 12bit [同一类型服务器允许4096台]
递增序号 16bit [该位数决定了每秒允许65536个不同的guid]
*/
private static ulong c_mark_time_stamp = 0xffffffff00000000;/*时间戳掩码*/
private static ulong c_mark_server_type = 0x00000000f0000000;/*服务器类型掩码*/
private static ulong c_mark_server_id = 0x000000000fff0000;/*服务器编号掩码*/
private static ulong c_mark_base = 0x000000000000ffff;/*本地ID编号掩码*/
private static uint c_baseId = 0;/*本地ID*/
private static readonly DateTime Jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
//生成唯一ID
public static ulong NewGuid(ServerType server, uint id)
{
uint serverType = (uint)server;
ulong timeStamp = (ulong)(DateTime.UtcNow - Jan1st1970).TotalSeconds;
ulong newId = ((timeStamp << 32) & c_mark_time_stamp) | ((serverType << 28) & c_mark_server_type) | ((id << 16) & c_mark_server_id) | (c_baseId & c_mark_base);
c_baseId++;
return newId;
}
//根据唯一ID获取所在服务器类型与服务器编号
public static void GetServer(ulong guid, out ServerType type, out uint id)
{
type = (ServerType)((guid & c_mark_server_type) >> 28);
id = (uint)((guid & c_mark_server_id) >> 16);
}
}
C++版本:
const u_int64_t c_mark_time_stamp = 0xffffffff00000000;/*时间戳掩码*/
const u_int64_t c_mark_district = 0x00000000fff00000;/*服务器区号掩码*/
const u_int64_t c_mark_plat = 0x00000000000ff000;/*服务器里的平台号掩码*/
const u_int64_t c_mark_base = 0x0000000000000fff;/*本地ID编号掩码*/
u_int64_t gen_new_guid()
{
static u_int32_t baseId = 0;
baseId++;
u_int64_t timeStamp = (u_int64_t)time(NULL);
u_int32_t districtNum = 1;/*这个服务器区号可以根据实际情况设置或者获取*/
u_int32_t platNum = 1;/*这个平台号可以根据实际情况设置或者获取*/
u_int64_t newId = ((timeStamp << 32)&c_mark_time_stamp) | ((districtNum << 20) & c_mark_district) | ((platNum << 12) & c_mark_plat) | (baseId & c_mark_base);
}