windows 顺序 GUID

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5585307/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 16:35:48  来源:igfitidea点击:

Sequential GUIDs

c#windowsdllguid

提问by Sean

I hope someone can answer this question.

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

How does the UuidCreateSequential method in the rpcrt4.dll class use to seed it's guids?

rpcrt4.dll 类中的 UuidCreateSequential 方法如何用于为其 guid 设置种子?

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.

我知道很多:Microsoft 更改了 UuidCreate 函数,因此它不再使用机器的 MAC 地址作为 UUID 的一部分。由于 CoCreateGuid 调用 UuidCreate 来获取其 GUID,因此其输出也发生了变化。如果您仍然喜欢按顺序生成 GUID(有助于将一组相关的 GUID 保存在系统注册表中),您可以使用 UuidCreateSequential 函数。

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?

问题背后的原因是。如果我使用此函数在 Web 集群中生成连续的 GUID,我如何确保 GUID 接近于一系列 GUID 而不会出现重复的 GUID?

回答by Ian Boyd

The Win32 UuidCreateSequentialcreates a Version 1uuid.

Win32UuidCreateSequential创建一个Version 1uuid

Here's some sample version 1 uuid's created on my computer using UuidCreateSequential:

这是在我的计算机上使用UuidCreateSequential以下命令创建的一些示例版本 1 uuid :

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):

首先需要注意的是,这些 uuid 包含我机器的 MAC 地址 ( B8AC6FBE26E1):

enter image description here

在此处输入图片说明

                        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.

因此,如果您希望不同的计算机生成彼此“接近”的 guid,您会感到失望。

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:

剩下的 10 个字节中的 7 个半字节是时间戳;自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

You can see that guid's created on the same machine by UuidCreateSequentialwill be together, as they are chronological.

您可以看到在同一台机器上创建的 guidUuidCreateSequential将放在一起,因为它们是按时间顺序排列的。



The 1you see is the version number, in this case meaning a time baseduuid. There are 5 defined versions:

1你看到的是版本号,在这种情况下,这意味着一个基于时间的UUID。有5个定义的版本:

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 wordcontains two things.

最后一句话包含两件事。

The lower 12 bits is the machine-specifc Clock Sequencenumber:

低 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

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)
  • 你换了网卡
  • 您生成的 UUID 距上一个不到 100 ns(并且时间戳会发生冲突)

So, again, any guid's created by UuidCreateSequentialwill (ideally) have the same Clock Sequencenumber, making them "near" to each other.

因此,再一次,由UuidCreateSequential意志创建的任何 guid (理想情况下)都具有相同的时钟序列号,使它们彼此“靠近”。

The final 2 bits, is called a Variant, and is always set to binary 10:

最后 2 位称为Variant,并且始终设置为 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 machinethey will be "near" to each other in a database.

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



But you want to know what actually happens with two sequential UUID's created on different computers.

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

Using our newfound knowledge of Version 1 guids, let's construct two guid's for the same timestamp from different machines, e.g.:

使用我们对版本 1 guid 的新知识,让我们为来自不同机器的相同时间戳构建两个 guid,例如:

{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 clusterby the guid:

首先让我们插入一堆带有顺序时间戳的 guid。首先创建一个临时表来存储我们的 guid,并通过 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.

注意:我以随机时间戳顺序插入它们,以说明 SQL Server 将对它们进行聚类。

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:

现在让我们插入 guid:

  • the same timestamps
  • but different node(i.e. MAC address):
  • 相同的时间戳
  • 但不同的节点(即 MAC 地址):

Insert the new guids from a "different" computer:

从“不同”的计算机插入新的 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}')

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 Nodebefore 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.

所以你有它。SQL Server 订单的节点Timestamp之前。从不同机器创建的 Uuid 不会聚集在一起。如果没有这样做会更好,但是该怎么办。

回答by Thomas

Rather than rely on the Win32 API, I typically use my own variant of a sequential guid which replaces eight bytes of the a standard guid with ticks from a datetime.

我通常不依赖 Win32 API,而是使用我自己的顺序 guid 变体,它将标准 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 );

回答by Bengie

You could have a central table that has the last known starting UID for a range and increment it.

您可以拥有一个中央表,该表具有范围的最后一个已知起始 UID 并递增它。

eg: DB1 creates a GUID {AA333F14-FCCD-4bee-9F8F-9D9BDF1B8766} and writes this to the table. DB2 comes online and sees {AA333F14-FCCD-4bee-9F8F-9D9BDF1B8766} and increments it by some set number, like 1,000,000,000,000,000 or something really high so you won't have any overlapping values.

例如:DB1 创建一个 GUID {AA333F14-FCCD-4bee-9F8F-9D9BDF1B8766} 并将其写入表中。DB2 联机并看到 {AA333F14-FCCD-4bee-9F8F-9D9BDF1B8766} 并将其增加某个设置数字,例如 1,000,000,000,000,000 或某些非常高的值,因此您不会有任何重叠的值。

But really, GUIDs are almost useless when used incrementally.

但实际上,当增量使用时,GUID 几乎毫无用处。

I guess the really question is, what are you using GUIDs for? If you want an incrmenting number, just use a 64bit int(aka, bigint)

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

回答by NKCSS

Not sure about the Win32 way, but you could use the 'undocumented' 'newSequentialID()' in MSSQL, if you have MSSQL Database connectivity.

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

I Say 'undocumented' because it's treated as incorrect when trying to save it as the default value for a MSSQL Identity column, and you have to override it and say you want to use it.

我说“未记录”是因为在尝试将其保存为 MSSQL 标识列的默认值时它被视为不正确,并且您必须覆盖它并说您想使用它。

回答by Reza

I changed Thomas, answer to have first 8 bytes as incremental

我改变了 Thomas,回答将前 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);

and result will be something like

结果将类似于

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