如何使用rpcrt4.dll类中的UuidCreateSequential方法种子它的guids?
我知道很多:
Microsoft更改了UuidCreate功能,因此它不再使用机器的MAC地址作为UUID的一部分.由于CoCreateGuid调用UuidCreate获取其GUID,其输出也改变了.如果您仍然按照顺序生成GUID(有助于将相关的GUID组保存在系统注册表中),则可以使用UuidCreateSequential函数.
问题背后的原因是.如果我使用此功能在Web集群中生成顺序GUID,那么如何确保GUID接近一系列GUID,而不会重复GUID?
解决方法
Version 1
uuid.
以下是使用UuidCreateSequential在我的电脑上创建的一些示例版本1 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} {220FB46C-63D1-11E1-80DB-B8AC6FBE26E1}
首先要注意的是,这些uuid包含我的机器的MAC地址(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
所以如果你希望不同的计算机产生相互“接近”的指针,那么你将会失望.
我们来看看其余的值.
其余10个字节的七个半字节是时间戳;从00:00:00 1582年10月15日起的间隔时间为100ns.将这些时间戳记字节重新排列在一起:
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
您可以看到,由UuidCreateSequential在同一台机器上创建的GUID将在一起,因为它们是按时间顺序的.
你看到的1是版本号,在这种情况下是一个基于时间的uuid.有5个定义的版本:
> 1:基于时间的版本(UuidCreateSequential)
> 2:DCE安全版本,带有嵌入式POSIX UID
> 3:使用MD5散列的基于名称的版本
> 4:随机或伪随机生成的版本(UuidCreate)
> 5:使用SHA-1散列的基于名称的版本
赠送:
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
最后一句话包含两件事.
低12位是机器特定的时钟序列号:
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
如果:
你切换网卡
你生成的UUID从最后一个不到100ns(并且时间戳会相撞)
因此,再次,由UuidCreateSequential创建的任何guid将(理想情况下)具有相同的时钟序列号,使它们彼此“靠近”.
最后的2位称为Variant,并且始终设置为二进制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
所以你有它.顺序方向是顺序的;并且如果您在同一台计算机上创建它们,那么它们将在数据库中彼此“靠近”.
但是您想知道在不同的计算机上创建的两个连续的UUID实际发生了什么.
使用我们对版本1 guids的新发现的知识,让我们从不同的机器构造相同时间戳的两个guid,例如:
{1BE8D85D-63D1-11E1-80DB-B8AC6FBE26E1} {1BE8D85D-63D1-11E1-80DB-123456789ABC}
首先让我们用连续的时间戳插入一堆guid.首先创建一个临时表来存储我们的guid,并通过guid进行聚类:
--DROP table #uuidOrderingTest CREATE TABLE #uuidOrderingTest ( uuid uniqueidentifier not null ) CREATE clustered index IX_uuidorderingTest_uuid ON #uuidOrderingTest ( uuid )
现在插入数据:
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}')
注意:我以随机时间戳顺序插入它们,以说明sql Server将它们聚类.
将行返回并查看顺序(时间戳)顺序的顺序:
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
现在可以插入guid:
>相同的时间戳
>但不同的节点(即MAC地址):
从“不同”的计算机插入新的guids:
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}')
并得到结果:
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
所以你有它.时间戳之前的sql Server订单节点.从不同机器创建的Uuid不会聚集在一起.如果没有这样做,会更好,但是whatcha会做.