顺序 GUID [英] Sequential GUIDs
问题描述
希望有人能回答这个问题.
rpcrt4.dll 类中的 UuidCreateSequential 方法如何用于为其 guid 设置种子?
我知道这么多:Microsoft 更改了 UuidCreate 函数,因此它不再使用机器的 MAC 地址作为 UUID 的一部分.由于 CoCreateGuid 调用 UuidCreate 来获取其 GUID,因此其输出也发生了变化.如果您仍然喜欢按顺序生成 GUID(有助于将相关的一组 GUID 保存在系统注册表中),您可以使用 UuidCreateSequential 函数.
问题背后的原因是.如果我使用此函数在 Web 集群中生成连续的 GUID,我如何确保 GUID 接近于一系列 GUID 而不会出现重复的 GUID?
Win32 UuidCreateSequential
创建了一个
UuidCreate
)给予:
时间戳版本节点========================================1E163D11BE8D85D 1 80DB B8AC6FBE26E11E163D11BE8D85E 1 80DB B8AC6FBE26E11E163D11BE8D85F 1 80DB B8AC6FBE26E11E163D11BE8D860 1 80DB B8AC6FBE26E11E163D11BE8D861 1 80DB B8AC6FBE26E11E163D11BE8D862 1 80DB B8AC6FBE26E11E163D11BE8D863 1 80DB B8AC6FBE26E11E163D11BE8D864 1 80DB B8AC6FBE26E11E163D11BE8D865 1 80DB B8AC6FBE26E11E163D1220FB46C 1 80DB B8AC6FBE26E1
最后一个词包含两件事.
低 12 位是机器特定的时钟序列编号:
时间戳版本时钟序列节点===================================================1E163D11BE8D85D 1 8 0DB B8AC6FBE26E11E163D11BE8D85E 1 8 0DB B8AC6FBE26E11E163D11BE8D85F 1 8 0DB B8AC6FBE26E11E163D11BE8D860 1 8 0DB B8AC6FBE26E11E163D11BE8D861 1 8 0DB B8AC6FBE26E11E163D11BE8D862 1 8 0DB B8AC6FBE26E11E163D11BE8D863 1 8 0DB B8AC6FBE26E11E163D11BE8D864 1 8 0DB B8AC6FBE26E11E163D11BE8D865 1 8 0DB B8AC6FBE26E11E163D1220FB46C 1 8 0DB B8AC6FBE26E1
在以下情况下,此机器范围的持久值会增加:
- 你换了网卡
- 您生成的 UUID 距离上一个不到 100 ns(并且时间戳会发生冲突)
因此,UuidCreateSequential
创建的任何 guid 将(理想情况下)具有相同的时钟序列编号,使它们接近"彼此.
最后的 2 位,称为 Variant,并且始终设置为二进制 10
:
时间戳版本变体时钟序列节点==========================================================1E163D11BE8D85D 1 8 0DB B8AC6FBE26E11E163D11BE8D85E 1 8 0DB B8AC6FBE26E11E163D11BE8D85F 1 8 0DB B8AC6FBE26E11E163D11BE8D860 1 8 0DB B8AC6FBE26E11E163D11BE8D861 1 8 0DB B8AC6FBE26E11E163D11BE8D862 1 8 0DB B8AC6FBE26E11E163D11BE8D863 1 8 0DB B8AC6FBE26E11E163D11BE8D864 1 8 0DB B8AC6FBE26E11E163D11BE8D865 1 8 0DB B8AC6FBE26E11E163D1220FB46C 1 8 0DB B8AC6FBE26E1
所以你有它.顺序 guid 是顺序的;如果您在同一台机器上创建它们,它们将接近"在数据库中相互关联.
但您想知道在不同计算机上创建的两个连续 UUID 实际会发生什么.
利用我们对版本 1 guid 的新知识,让我们为来自不同机器的相同时间戳构建两个 guid,例如:
{1BE8D85D-63D1-11E1-80DB-B8AC6FBE26E1}{1BE8D85D-63D1-11E1-80DB-123456789ABC}
首先让我们插入一堆带有顺序时间戳的 guid.首先创建一个临时表来存储我们的 guid,并由 guid 组成集群:
--DROP table #uuidOrderingTest创建表#uuidOrderingTest(uuid 唯一标识符不为空)创建聚集索引 IX_uuidorderingTest_uuid ON #uuidOrderingTest(用户名)
现在插入数据:
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D866-63D1-11E1-80DB-B8AC6FBE26E1}')插入 #uuidOrderingTest (uuid) 值 ('{1BE8D862-63D1-11E1-80DB-B8AC6FBE26E1}')插入 #uuidOrderingTest (uuid) 值 ('{1BE8D861-63D1-11E1-80DB-B8AC6FBE26E1}')插入 #uuidOrderingTest (uuid) 值 ('{1BE8D85E-63D1-11E1-80DB-B8AC6FBE26E1}')插入 #uuidOrderingTest (uuid) 值 ('{1BE8D864-63D1-11E1-80DB-B8AC6FBE26E1}')插入 #uuidOrderingTest (uuid) 值 ('{1BE8D863-63D1-11E1-80DB-B8AC6FBE26E1}')插入 #uuidOrderingTest (uuid) 值 ('{1BE8D85F-63D1-11E1-80DB-B8AC6FBE26E1}')插入 #uuidOrderingTest (uuid) 值 ('{1BE8D85D-63D1-11E1-80DB-B8AC6FBE26E1}')插入 #uuidOrderingTest (uuid) 值 ('{1BE8D865-63D1-11E1-80DB-B8AC6FBE26E1}')插入 #uuidOrderingTest (uuid) 值 ('{1BE8D860-63D1-11E1-80DB-B8AC6FBE26E1}')
注意:我以随机时间戳顺序插入它们,以说明 SQL Server 将对它们进行聚类.
取回行并查看它们的顺序(时间戳)顺序:
SELECT * FROM #uuidOrderingTest用户名---------------------1BE8D85D-63D1-11E1-80DB-B8AC6FBE26E11BE8D85E-63D1-11E1-80DB-B8AC6FBE26E11BE8D85F-63D1-11E1-80DB-B8AC6FBE26E11BE8D860-63D1-11E1-80DB-B8AC6FBE26E11BE8D861-63D1-11E1-80DB-B8AC6FBE26E11BE8D862-63D1-11E1-80DB-B8AC6FBE26E11BE8D863-63D1-11E1-80DB-B8AC6FBE26E11BE8D864-63D1-11E1-80DB-B8AC6FBE26E11BE8D865-63D1-11E1-80DB-B8AC6FBE26E11BE8D866-63D1-11E1-80DB-B8AC6FBE26E1
现在让我们插入 guid:
- 相同的时间戳
- 但不同的节点(即MAC地址):
从不同的"目录插入新的 guid电脑:
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D866-63D1-11E1-80DB-123456789ABC}')插入 #uuidOrderingTest (uuid) 值 ('{1BE8D862-63D1-11E1-80DB-123456789ABC}')插入 #uuidOrderingTest (uuid) 值 ('{1BE8D861-63D1-11E1-80DB-123456789ABC}')插入 #uuidOrderingTest (uuid) 值 ('{1BE8D85E-63D1-11E1-80DB-123456789ABC}')插入 #uuidOrderingTest (uuid) 值 ('{1BE8D864-63D1-11E1-80DB-123456789ABC}')插入 #uuidOrderingTest (uuid) 值 ('{1BE8D863-63D1-11E1-80DB-123456789ABC}')插入 #uuidOrderingTest (uuid) 值 ('{1BE8D85F-63D1-11E1-80DB-123456789ABC}')插入 #uuidOrderingTest (uuid) 值 ('{1BE8D85D-63D1-11E1-80DB-123456789ABC}')插入 #uuidOrderingTest (uuid) 值 ('{1BE8D865-63D1-11E1-80DB-123456789ABC}')插入 #uuidOrderingTest (uuid) 值 ('{1BE8D860-63D1-11E1-80DB-123456789ABC}')
并得到结果:
uuid---------------------1BE8D85D-63D1-11E1-80DB-123456789ABC1BE8D85E-63D1-11E1-80DB-123456789ABC1BE8D85F-63D1-11E1-80DB-123456789ABC1BE8D860-63D1-11E1-80DB-123456789ABC1BE8D861-63D1-11E1-80DB-123456789ABC1BE8D862-63D1-11E1-80DB-123456789ABC1BE8D863-63D1-11E1-80DB-123456789ABC1BE8D864-63D1-11E1-80DB-123456789ABC1BE8D865-63D1-11E1-80DB-123456789ABC1BE8D866-63D1-11E1-80DB-123456789ABC1BE8D85D-63D1-11E1-80DB-B8AC6FBE26E11BE8D85E-63D1-11E1-80DB-B8AC6FBE26E11BE8D85F-63D1-11E1-80DB-B8AC6FBE26E11BE8D860-63D1-11E1-80DB-B8AC6FBE26E11BE8D861-63D1-11E1-80DB-B8AC6FBE26E11BE8D862-63D1-11E1-80DB-B8AC6FBE26E11BE8D863-63D1-11E1-80DB-B8AC6FBE26E11BE8D864-63D1-11E1-80DB-B8AC6FBE26E11BE8D865-63D1-11E1-80DB-B8AC6FBE26E11BE8D866-63D1-11E1-80DB-B8AC6FBE26E1
所以你有它.时间戳之前的SQL Server命令的节点.从不同机器创建的 Uuid 不会聚集在一起.如果不这样做会更好,但要做什么.
I hope someone can answer this question.
How does the UuidCreateSequential method in the rpcrt4.dll class use to seed it's guids?
I know this much: Microsoft changed the UuidCreate function so it no longer uses the machine's MAC address as part of the UUID. Since CoCreateGuid calls UuidCreate to get its GUID, its output also changed. If you still like the GUIDs to be generated in sequential order (helpful for keeping a related group of GUIDs together in the system registry), you can use the UuidCreateSequential function.
The reason behind the question is. If I use this function to generate sequential GUIDs in a web cluster, how can I ensure that the GUIDs are close to a range of GUIDs without the potential of the GUID being duplicated?
The Win32 UuidCreateSequential
creates a Version 1
uuid.
Here's some sample version 1 uuid's created on my computer using UuidCreateSequential
:
GuidToString Raw bytes
====================================== =================================================
{1BE8D85D-63D1-11E1-80DB-B8AC6FBE26E1} 1B E8 D8 5D 63 D1 11 E1 80 DB B8 AC 6F BE 26 E1
{1BE8D85E-63D1-11E1-80DB-B8AC6FBE26E1} 1B E8 D8 5E 63 D1 11 E1 80 DB B8 AC 6F BE 26 E1
{1BE8D85F-63D1-11E1-80DB-B8AC6FBE26E1} 1B E8 D8 5F 63 D1 11 E1 80 DB B8 AC 6F BE 26 E1
{1BE8D860-63D1-11E1-80DB-B8AC6FBE26E1} 1B E8 D8 60 63 D1 11 E1 80 DB B8 AC 6F BE 26 E1
{1BE8D861-63D1-11E1-80DB-B8AC6FBE26E1} 1B E8 D8 61 63 D1 11 E1 80 DB B8 AC 6F BE 26 E1
{1BE8D862-63D1-11E1-80DB-B8AC6FBE26E1} 1B E8 D8 62 63 D1 11 E1 80 DB B8 AC 6F BE 26 E1
{1BE8D863-63D1-11E1-80DB-B8AC6FBE26E1} 1B E8 D8 63 63 D1 11 E1 80 DB B8 AC 6F BE 26 E1
{1BE8D864-63D1-11E1-80DB-B8AC6FBE26E1} 1B E8 D8 64 63 D1 11 E1 80 DB B8 AC 6F BE 26 E1
{1BE8D865-63D1-11E1-80DB-B8AC6FBE26E1} 1B E8 D8 65 63 D1 11 E1 80 DB B8 AC 6F BE 26 E1
{220FB46C-63D1-11E1-80DB-B8AC6FBE26E1} 22 0F B4 6C 63 D1 11 E1 80 DB B8 AC 6F BE 26 E1
The first thing that's important to note that these uuid contain my machine's MAC address (B8AC6FBE26E1
):
Node
======================= ============
1BE8D85D-63D1-11E1-80DB B8AC6FBE26E1
1BE8D85E-63D1-11E1-80DB B8AC6FBE26E1
1BE8D85F-63D1-11E1-80DB B8AC6FBE26E1
1BE8D860-63D1-11E1-80DB B8AC6FBE26E1
1BE8D861-63D1-11E1-80DB B8AC6FBE26E1
1BE8D862-63D1-11E1-80DB B8AC6FBE26E1
1BE8D863-63D1-11E1-80DB B8AC6FBE26E1
1BE8D864-63D1-11E1-80DB B8AC6FBE26E1
1BE8D865-63D1-11E1-80DB B8AC6FBE26E1
220FB46C-63D1-11E1-80DB B8AC6FBE26E1
So if you're hoping for different computers to generate guid's that are "close" to each other, you're going to be disappointed.
Let's look at the rest of the values.
Seven and a half bytes of the remaining 10 bytes are a timestamp; the number of 100ns intervals since 00:00:00 15 October 1582. Rearranging those timestamp bytes together:
Timestamp Node
=============== ====== ============
1E163D11BE8D85D 1-80DB B8AC6FBE26E1
1E163D11BE8D85E 1-80DB B8AC6FBE26E1
1E163D11BE8D85F 1-80DB B8AC6FBE26E1
1E163D11BE8D860 1-80DB B8AC6FBE26E1
1E163D11BE8D861 1-80DB B8AC6FBE26E1
1E163D11BE8D862 1-80DB B8AC6FBE26E1
1E163D11BE8D863 1-80DB B8AC6FBE26E1
1E163D11BE8D864 1-80DB B8AC6FBE26E1
1E163D11BE8D865 1-80DB B8AC6FBE26E1
1E163D1220FB46C 1-80DB B8AC6FBE26E1
You can see that guid's created on the same machine by UuidCreateSequential
will be together, as they are chronological.
The 1
you see is the version number, in this case meaning a time based uuid. There are 5 defined versions:
- 1: time based version (
UuidCreateSequential
) - 2: DCE Security version, with embedded POSIX UIDs
- 3: Name-based version that uses MD5 hashing
- 4: Randomly or pseudo-randomly generated version (
UuidCreate
) - 5: Name-based version that uses SHA-1 hashing
- 6: The version RFC 4122 forgot (unofficial)
Giving:
Timestamp Version Node
=============== ======= ==== ============
1E163D11BE8D85D 1 80DB B8AC6FBE26E1
1E163D11BE8D85E 1 80DB B8AC6FBE26E1
1E163D11BE8D85F 1 80DB B8AC6FBE26E1
1E163D11BE8D860 1 80DB B8AC6FBE26E1
1E163D11BE8D861 1 80DB B8AC6FBE26E1
1E163D11BE8D862 1 80DB B8AC6FBE26E1
1E163D11BE8D863 1 80DB B8AC6FBE26E1
1E163D11BE8D864 1 80DB B8AC6FBE26E1
1E163D11BE8D865 1 80DB B8AC6FBE26E1
1E163D1220FB46C 1 80DB B8AC6FBE26E1
The last word contains two things.
The lower 12 bits is the machine-specifc Clock Sequence number:
Timestamp Version Clock Sequence Node
=============== ======= = ================ ============
1E163D11BE8D85D 1 8 0DB B8AC6FBE26E1
1E163D11BE8D85E 1 8 0DB B8AC6FBE26E1
1E163D11BE8D85F 1 8 0DB B8AC6FBE26E1
1E163D11BE8D860 1 8 0DB B8AC6FBE26E1
1E163D11BE8D861 1 8 0DB B8AC6FBE26E1
1E163D11BE8D862 1 8 0DB B8AC6FBE26E1
1E163D11BE8D863 1 8 0DB B8AC6FBE26E1
1E163D11BE8D864 1 8 0DB B8AC6FBE26E1
1E163D11BE8D865 1 8 0DB B8AC6FBE26E1
1E163D1220FB46C 1 8 0DB B8AC6FBE26E1
This machine-wide persistent value is incremented if:
- you switched network cards
- you generated a UUID less than 100 ns from the last one (and the timestamp would collide)
So, again, any guid's created by UuidCreateSequential
will (ideally) have the same Clock Sequence number, making them "near" to each other.
The final 2 bits, is called a Variant, and is always set to binary 10
:
Timestamp Version Variant Clock Sequence Node
=============== ======= ======= ================ ============
1E163D11BE8D85D 1 8 0DB B8AC6FBE26E1
1E163D11BE8D85E 1 8 0DB B8AC6FBE26E1
1E163D11BE8D85F 1 8 0DB B8AC6FBE26E1
1E163D11BE8D860 1 8 0DB B8AC6FBE26E1
1E163D11BE8D861 1 8 0DB B8AC6FBE26E1
1E163D11BE8D862 1 8 0DB B8AC6FBE26E1
1E163D11BE8D863 1 8 0DB B8AC6FBE26E1
1E163D11BE8D864 1 8 0DB B8AC6FBE26E1
1E163D11BE8D865 1 8 0DB B8AC6FBE26E1
1E163D1220FB46C 1 8 0DB B8AC6FBE26E1
So there you have it. Sequential guid's are sequential; and if you create them on the same machine they will be "near" to each other in a database.
But you want to know what actually happens with two sequential UUID's created on different computers.
Using our newfound knowledge of Version 1 guids, let's construct two guid's for the same timestamp from different machines, e.g.:
{1BE8D85D-63D1-11E1-80DB-B8AC6FBE26E1}
{1BE8D85D-63D1-11E1-80DB-123456789ABC}
First let's insert a bunch of guid's with sequential timestamps. First create a temporary table to store our guid's in, and cluster by the guid:
--DROP table #uuidOrderingTest
CREATE TABLE #uuidOrderingTest
(
uuid uniqueidentifier not null
)
CREATE clustered index IX_uuidorderingTest_uuid ON #uuidOrderingTest
(
uuid
)
Now insert the data:
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D866-63D1-11E1-80DB-B8AC6FBE26E1}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D862-63D1-11E1-80DB-B8AC6FBE26E1}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D861-63D1-11E1-80DB-B8AC6FBE26E1}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D85E-63D1-11E1-80DB-B8AC6FBE26E1}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D864-63D1-11E1-80DB-B8AC6FBE26E1}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D863-63D1-11E1-80DB-B8AC6FBE26E1}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D85F-63D1-11E1-80DB-B8AC6FBE26E1}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D85D-63D1-11E1-80DB-B8AC6FBE26E1}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D865-63D1-11E1-80DB-B8AC6FBE26E1}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D860-63D1-11E1-80DB-B8AC6FBE26E1}')
Note: i insert them in random timestamp order, to illustrate that SQL Server will cluster them.
Get the rows back and see what order they're in sequential (timestamp) order:
SELECT * FROM #uuidOrderingTest
uuid
------------------------------------
1BE8D85D-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D85E-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D85F-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D860-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D861-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D862-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D863-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D864-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D865-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D866-63D1-11E1-80DB-B8AC6FBE26E1
Now lets insert guid's with:
- the same timestamps
- but different node (i.e. MAC address):
Insert the new guids from a "different" computer:
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D866-63D1-11E1-80DB-123456789ABC}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D862-63D1-11E1-80DB-123456789ABC}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D861-63D1-11E1-80DB-123456789ABC}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D85E-63D1-11E1-80DB-123456789ABC}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D864-63D1-11E1-80DB-123456789ABC}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D863-63D1-11E1-80DB-123456789ABC}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D85F-63D1-11E1-80DB-123456789ABC}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D85D-63D1-11E1-80DB-123456789ABC}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D865-63D1-11E1-80DB-123456789ABC}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D860-63D1-11E1-80DB-123456789ABC}')
And get the results:
uuid
------------------------------------
1BE8D85D-63D1-11E1-80DB-123456789ABC
1BE8D85E-63D1-11E1-80DB-123456789ABC
1BE8D85F-63D1-11E1-80DB-123456789ABC
1BE8D860-63D1-11E1-80DB-123456789ABC
1BE8D861-63D1-11E1-80DB-123456789ABC
1BE8D862-63D1-11E1-80DB-123456789ABC
1BE8D863-63D1-11E1-80DB-123456789ABC
1BE8D864-63D1-11E1-80DB-123456789ABC
1BE8D865-63D1-11E1-80DB-123456789ABC
1BE8D866-63D1-11E1-80DB-123456789ABC
1BE8D85D-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D85E-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D85F-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D860-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D861-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D862-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D863-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D864-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D865-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D866-63D1-11E1-80DB-B8AC6FBE26E1
So there you have it. SQL Server order's Node before Timestamp. Uuid created from different machines will not be clustered together. Would have been better if it hadn't done so, but whatcha gonna do.
这篇关于顺序 GUID的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!