网游服务器中的GUID(唯一标识码)实现-基于snowflake算法
本文中的算法采用twitter的snowflake算法,具体请搜索介绍,原来是用Scala写的,因我项目需要,改写成C++语言,主要用于高效的生成唯一的ID, 核心算法就是毫秒级时间(41位)+机器ID(10位)+毫秒内序列(12位).
网上也有好多PHP写的插件模块,核心用了网络通讯将生成的ID发送给PHP使用,没深入研究PHP的模块写法。
废话不多说了,还是直接上代码好了。
uuid.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
#ifndef __UTIL_UUID_H__
#define __UTIL_UUID_H__
#include <stdint.h>
namespace
utils
{
// twitter snowflake算法
// 64 63--------------22---------12---------0
// 符号位 | 41位时间 |10位机器码|12位自增码|
extern
uint64_t
get_time
(
)
;
class
unique_id_t
{
public
:
unique_id_t
(
)
;
~
unique_id_t
(
)
;
void
set_epoch
(
uint64_t
epoch
)
;
void
set_machine
(
int32_t
machine
)
;
int64_t
generate
(
)
;
private
:
uint64_t
epoch_
;
uint64_t
time_
;
int32_t
machine_
;
int32_t
sequence_
;
}
;
}
#endif // !__UTIL_UUID_H__
|
uuid.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
#include "uuid.h"
#if defined(__GUNC__)
#include <sys/time.h>
#include <unistd.h>
#define EPOCHFILETIME 11644473600000000ULL
#else
#include <windows.h>
#include <time.h>
#define EPOCHFILETIME 11644473600000000Ui64
#endif
namespace
utils
{
uint64_t
get_time
(
)
{
#ifdef __GUNC__
struct
timeval
tv
;
gettimeofday
(
&tv
,
NULL
)
;
uint64
time
=
tv
.
tv_usec
;
time
/=
1000
;
time
+=
(
tv
.
tv_sec
*
1000
)
;
return
time
;
#else
FILETIME
filetime
;
uint64_t
time
=
0
;
GetSystemTimeAsFileTime
(
&filetime
)
;
time
|=
filetime
.
dwHighDateTime
;
time
<<
=
32
;
time
|=
filetime
.
dwLowDateTime
;
time
/=
10
;
time
-=
EPOCHFILETIME
;
return
time
/
1000
;
#endif
}
unique_id_t
::
unique_id_t
(
)
{
epoch_
=
0
;
time_
=
0
;
machine_
=
0
;
sequence_
=
0
;
}
unique_id_t
::
~
unique_id_t
(
)
{
}
void
unique_id_t
::
set_epoch
(
uint64_t
epoch
)
{
epoch_
=
epoch
;
}
void
unique_id_t
::
set_machine
(
int32_t
machine
)
{
machine_
=
machine
;
}
int64_t
unique_id_t
::
generate
(
)
{
int64_t
value
=
0
;
uint64_t
time
=
get_time
(
)
-
epoch_
;
// 保留后41位时间
value
=
time
<<
22
;
// 中间10位是机器ID
value
|=
(
machine_
&
0x3FF
)
<<
12
;
// 最后12位是sequenceID
value
|=
sequence_
++
&
0xFFF
;
if
(
sequence_
==
0x1000
)
{
sequence_
=
0
;
}
return
value
;
}
}
#ifdef __TEST__
#include <iostream>
void
test
(
)
{
utils
::
unique_id_t
*
u_id_ptr
=
new
utils
::
unique_id_t
(
)
;
u_id_ptr
->
set_epoch
(
uint64_t
(
1367505795100
)
)
;
u_id_ptr
->
set_machine
(
int32_t
(
100
)
)
;
for
(
int
i
=
0
;
i
<
1024
;
++
i
)
{
std
::
cout
<<
u_id_ptr
->
generate
(
)
<<
std
::
endl
;
;
}
}
#endif
|
这样的唯一ID就可以用来表示你系统中使用的例如物品唯一ID,坐骑唯一ID等等数据,方便记录和追踪。