顺序GUID

我希望有人能回答这个问题。

如何在rpcrt4.dll类的UuidCreateSequential方法使用它的guid?

我知道这一点:微软更改了UuidCreatefunction,因此不再使用机器的MAC地址作为UUID的一部分。 由于CoCreateGuid调用UuidCreate来获取它的GUID,所以它的输出也改变了。 如果您仍然喜欢按顺序生成的GUID(有助于在系统registry中保留相关的一组GUID),则可以使用UuidCreateSequential函数。

问题背后的原因是。 如果我使用此函数在Web群集中生成顺序的GUID,如何确保GUID接近一系列GUID而没有可能重复的GUID?

Solutions Collecting From Web of "顺序GUID"

Win32 UuidCreateSequential创建一个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个字节中的七个半字节是时间戳 ; 1582年10月15日00:00:00开始 ,间隔时间为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在同一台机器上创建的UuidCreateSequential将在一起,因为它们是按时间顺序排列的。


你看到的是版本号 ,在这种情况下意味着基于时间的 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距离最后一个小于100 ns(时间戳会发生冲突)

所以,再一次,由UuidCreateSequential创建的UuidCreateSequential (理想情况下)将具有相同的时钟序列号,使它们彼此“靠近”。

最后的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 

所以你有它。 顺序guid是顺序的; 如果你在同一台机器上创建它们,它们将在数据库中彼此“靠近”。


但是你想知道在不同的计算机上创建两个连续的UUID实际上发生了什么。

使用我们对第一版GUID的新知识,让我们从不同的机器构造两个相同时间戳的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地址):

从“不同的”计算机插入新的GUID:

 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不会聚集在一起。 如果不这样做会更好,但是会怎么做。

我通常使用自己的顺序guid变体,而不是依赖于Win32 API,它使用日期时间的标记来替换标准guid的八个字节。

 var guidBinary = new byte[16]; Array.Copy( Guid.NewGuid().ToByteArray(), 0, guidBinary, 0, 8 ); Array.Copy( BitConverter.GetBytes( DateTime.Now.Ticks ), 0, guidBinary, 8, 8 ); return new Guid( guidBinary ); 

不知道Win32的方式,但如果你有MSSQL数据库连接,你可以在MSSQL中使用“未记录的” newSequentialID() 。

我说'没有记录',因为它被视为不正确,当它试图将其保存为MSSQL标识列的默认值,你必须覆盖它,并说你想使用它。

你可以有一个中央表,有一个范围的最后一个已知的开始的UID,并增加它。

例如:DB1创建一个GUID {AA333F14-FCCD-4bee-9F8F-9D9BDF1B8766}并将其写入表中。 DB2联机并看到{AA333F14-FCCD-4bee-9F8F-9D9BDF1B8766},并将其递增一些设置数量,如1,000,000,000,000,000或者真的很高,这样就不会有任何重叠的值。

但是,实际上,增量使用GUID几乎是无用的。

我想真正的问题是,你在用什么GUID? 如果你想要一个数字,只需要使用一个64位int(aka,bigint)

我改变了托马斯,回答有前8个字节增量

  var guidBinary = new byte[16]; Array.Copy(BitConverter.GetBytes(DateTime.Now.Ticks), 0, guidBinary, 0, 8); Array.Copy(Guid.NewGuid().ToByteArray(), 8, guidBinary, 8, 8); return new Guid(guidBinary); 

结果会是这样的

 b0c99468-714a-08d4-88bd-39e0b53455fb b122b4b8-714a-08d4-9b12-924e850ad2fe b1254cf0-714a-08d4-b7c9-954d36290ce5 b12573ff-714a-08d4-b000-632c3a58874d