C# 如何生成 GUID?

发布于 2024-08-13 21:47:55 字数 25 浏览 2 评论 0原文

C# 中的 GUID 是如何生成的?

How are GUIDs generated in C#?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

与风相奔跑 2024-08-20 21:47:55

Raymond Chen 的博客上有一篇非常棒的文章,它描述了 GUID 是如何生成的,特别是为什么不能保证 GUID 的子字符串是唯一的。

基本上,GUID 是使用以下组合生成的:

  • 用于生成 GUID 的计算机的 MAC 地址(因此,除非重复使用 MAC 地址,否则在不同计算机上生成的 GUID 是唯一的)
  • 时间戳(因此同一台机器上不同时间生成的 GUID 是唯一的)
  • 额外的“紧急唯一标识符位”(这些用于确保同一台机器上几乎完全相同的时间生成的 GUID是唯一的)
  • 算法的标识符(以便使用不同算法生成的 GUID 是唯一的)

但是,这只是用于生成 GUID 的一种特定算法(尽管我相信它是使用的)由 .NET 框架),并且不是 . NET 框架

There's a really good article on Raymond Chen's blog that describes how GUIDs are generated, and in particular why a substring of a guid is not guaranteed to be unique.

Basically, a a GUID is generated using a combination of:

  • The MAC address of the machine used to generate the GUID (so GUIDs generated on different machines are unique unless MAC addresses are re-used)
  • Timestamp (so GUIDs generated at different times on the same machine are unique)
  • Extra "emergency uniquifier bits" (these are used to ensure that GUIDs generated at nearly exactly the same time on the same machine are unique)
  • An identifier for the algorithm (so that GUIDs generated with a different algorithm are unique)

However, this is only 1 particular algorithm used for generating GUIDs (although I believe it's the one used by the .NET framework), and is not the one used by the .NET framework.

巷子口的你 2024-08-20 21:47:55

该算法在此处记录为全局唯一标识符

The algorithm is documented here as Globally unique identifier

黄昏下泛黄的笔记 2024-08-20 21:47:55

原问题:

Guid 如何生成它的标识符?它的输出将如何
如果我使用以下代码 Guid g = Guid.NewGuid();

输出是数字和字母的组合还是
仅数字就会在那里???

.Net System.Guid 只是一个 128 位整数(16 字节)。数字和字母与此无关。您可以使用 ToString() 方法查看 Guid 的各种“人类可读”版本,其中包括数字 0-9 和字母 AF(表示十六进制值),但这完全取决于您想要如何输出它。

Original question:

How the Guid is generating it's identifier?? How will be it's output
if I use the following code Guid g = Guid.NewGuid();

Whether the output will be the combination of numbers and lettters or
the numbers alone will be there???

A .Net System.Guid is just a 128-bit integer (16 bytes). Numbers and letters have nothing to do with it. You can use the ToString() method to see various "human-readable" versions of a Guid, which include numbers 0-9 and letters A-F (representing hex values), but that's all up to you how you want to output it.

司马昭之心 2024-08-20 21:47:55

这取决于。对于 Unix GUID 中的 .NET Core,是通过创建 128 位随机数并执行几个按位操作来生成的。在 .NET Core for Windows 和 .NET Framework 中,它对 Windows 函数进行远程过程调用 UuidCreate (因此它们的生成方式完全取决于您的 Windows 版本)。对于 Unix 和最新版本的 Windows,您会注意到有一个十六进制数字始终是 4。这是因为它是 Uuid 4 的版本号,这意味着它们是用随机字节生成的。 GUID 过去是通过时间戳和 MAC 地址等内容生成的,但这成为了攻击媒介,因为它告诉最终用户有关系统的信息并帮助他们更轻松地预测未来的 GUID。

It depends. For .NET Core in Unix GUIDs, are generated by creating a random number of 128 bits and and doing a couple bit wise operations. In .NET Core for Windows and .NET framework it makes a remote procedure call to the Windows function UuidCreate (so it's completely up to your Windows version on how they are generated). For Unix and recent versions of Windows, you'll notice that there is one hex digit that is always a 4. That is because it the version number for the Uuid 4, which just means they are generated with random bytes. GUIDs used to be generated with things like the timestamp and MAC address, but that became an attack vector because it told end users information about the system and helped them predict future GUIDs easier.

林空鹿饮溪 2024-08-20 21:47:55

正如 RFC 中提到的,除了“随机 16 字节”之外,还有其他形式的 GUID。某些 Microsoft 产品(例如 SQL Server)可以选择生成这些“顺序 GUID”,这些 GUID 基于“系统中第一个网卡的 MAC 地址 + 基于系统时间的不断增加的计数器”的组合。

这些“顺序 GUID”具有良好的属性,当用作具有聚集索引的数据库主键时,总是将新记录附加到数据库表的“末尾”。这有助于防止数据库索引碎片和页面拆分。

如果使用随机 GUID 作为具有聚集索引的数据库主键,则从物理分配的角度来看,新记录将随机插入到表的“中间”,随着时间的推移,这会导致索引碎片和部分满的数据库页面。

使用顺序 GUID 仍然允许您在多个系统上独立生成 GUID,并确信不会发生任何冲突(如果不为每个系统分配“范围”或不同的种子和增量,则使用顺序整数作为主键无法获得该属性,这对于大型分布式应用程序来说是一场管理噩梦)。

There are also other forms of GUID besides "random 16 bytes", as mentioned in the RFC. Some Microsoft products (SQL Server for instance) can optionally generate these "sequential GUIDs" which are based on a combination of "MAC address of first network card in the system + ever-increasing counter based on system time".

These "sequential GUIDs" have the nice property of always appending new records to the "end" of a database table when used as a database primary key with a clustered index. This helps prevent database index fragmentation and page splits.

If random GUIDs are used as database primary keys with clustered indexes, new records will be inserted randomly in the "middle" of a table from a physical allocation standpoint, which leads to index fragmentation and partially-full database pages over time.

Using sequential GUIDs still allows you to generate GUIDs independently on multiple systems and be confident there will not be any collisions (a property that you do not get using sequential integers as primary keys without allocating "ranges" or different seeds and increments to each system, which is an administrative nightmare in large distributed applications).

家住魔仙堡 2024-08-20 21:47:55

有关 WikipediaMSDN

简而言之,GUID 是一个随机的 128 位整数,但我们使用十六进制数字对其进行格式化,以便它们易于读取(这是您看到的 8-4-4-4-12 格式)。至于它是如何生成的,请参阅链接的维基百科文章。

Details on Wikipedia and MSDN.

In short, a GUID is a random 128-bit integer, but we format them using hex digits so that they are easily readable (this is the 8-4-4-4-12 format that you see). As far as how its generated, see the linked Wikipedia article.

草莓味的萝莉 2024-08-20 21:47:55

GUID 的位分解如下:

  • 60 位时间戳
  • 48 位计算机标识符
  • 14 位唯一标识符
  • 6 位固定

总共 128 位。

The bits of the GUID break down like this:

  • 60 bits of timestamp
  • 48 bits of computer identifier
  • 14 bits of uniquifier
  • 6 bits are fixed

Total of 128 bits.

生死何惧 2024-08-20 21:47:55

我们可以直接根据生成的 GUID 进行检查。我更喜欢一些源文档,但说实话,维基百科的概要非常好。第一个相关部分是关于GUID 变体。摘要:为了确定 GUID 类型,我们必须查看变体以及可能的版本

哪个变体(和版本)是 .NET 生成的 GUID?

变体由第 9 个八位字节的初始位指示。这是通过将初始位“固定”到 010110111 来完成的。使用

string show(Guid g) => $"{g}: fam {Convert.ToString(g.ToByteArray()[8], 2)}";
show(Guid.NewGuid())

我们可能会得到“1b579ecd-b72c-4550-b10b-f8dd41699ac1:fam 10110001”。该系列固定为 10OSF DCE UUID变体 2。该变体定义了一个版本,保存在第 7 个八位位组的更重要的“半字节”中。

但是,有一个复杂的因素:编码的字节顺序。这些基于 MS 的部分以 little-endian 格式存储。让我们看一下:用另一种快速方法,

void SeeOrder(Guid g) => Console.WriteLine($"{g}\n{g:N}\n{string.Join("", g.ToByteArray().Select(b => $"{b:x2}"))}"); 

我们会看到类似的结果

dd3f9bdf-ba47-4411-84c8-6cfcc5d39bb5
dd3f9bdfba47441184c86cfcc5d39bb5
df9b3fdd47ba114484c86cfcc5d39bb5

前三组被转置,因为每组都是一个完整的整数(两个用于时间,一个保留;分别为 32、16 和 16 位)。最后两组不是,因为最后 8 个八位字节是一个“字符串”:1 个保留八位字节(表示“族”)和 7 个“节点”八位字节。

因此,第 7 个版本的八位字节实际上被编码为第 8 个版本(索引 7)。展开 show 以突出显示版本:

string show(Guid g) => $"{g}: fam {Convert.ToString(g.ToByteArray()[8], 2)}, ver {g.ToByteArray()[7].ToString("x")}";

我们将得到 "154573de-d420-433b-bb25-aff50590038b: fam 10111011, ver 43"。所讨论的半字节是4,因此是版本4:伪随机生成

正如您在上面的示例中看到的,变体 2 版本显示为第三组的第一个十六进制字符。您会注意到,在 .NET GUID 中,它始终是 4。读完本文后,您将永远寻找 4。

不客气。

We can check this directly against generated GUIDs. I'd prefer some source documents, but TBH the Wikipedia rundown is pretty good. The first relevant section is on GUID Variants. Summary: in order to determine the GUID type, we'll have to look at the variant and possibly a version.

Which variant (& version) are .NET-generated GUIDs?

Variant is indicated by the initial bits of the 9th octet. It is done by "pinning" the initial bits to 0, 10, 110 or 111. Using

string show(Guid g) => 
quot;{g}: fam {Convert.ToString(g.ToByteArray()[8], 2)}";
show(Guid.NewGuid())

we might get "1b579ecd-b72c-4550-b10b-f8dd41699ac1: fam 10110001". The family is pinned to 10, OSF DCE UUID or variant 2. This variant defines a version, held in the more significant "nibble" of the 7th octet.

BUT, there is a complicating factor: endianness in encoding. These MS-based sections are stored in a little-endian format. Let's take a look: with another quick method

void SeeOrder(Guid g) => Console.WriteLine(
quot;{g}\n{g:N}\n{string.Join("", g.ToByteArray().Select(b => 
quot;{b:x2}"))}"); 

we'll see a result like

dd3f9bdf-ba47-4411-84c8-6cfcc5d39bb5
dd3f9bdfba47441184c86cfcc5d39bb5
df9b3fdd47ba114484c86cfcc5d39bb5

The first three groups are transposed, because each is a complete integer (two for time, one reserved; 32, 16 and 16 bits respectively). The last two groups are not, because the last 8 octets are a "string": 1 reserved octet (where the "family" is represented) and 7 "node" octets.

So the 7th version octet is actually encoded as the 8th (index 7). Expanding show to highlight the version:

string show(Guid g) => 
quot;{g}: fam {Convert.ToString(g.ToByteArray()[8], 2)}, ver {g.ToByteArray()[7].ToString("x")}";

We'll get "154573de-d420-433b-bb25-aff50590038b: fam 10111011, ver 43". The nibble in question is the 4, thus version 4: pseudo-random generation.

As you can see in the above examples, the variant 2 version shows up as the first hex char of the 3rd group. You'll notice in .NET GUIDs, it will always be 4. After reading this you'll never not look for that 4.

You're welcome.

感情旳空白 2024-08-20 21:47:55

Guid 是一个独特的数字,具有数十亿种排列,由十六进制和分组数字的混合组成。它是根据不同的因素生成的,如时间、Windows 版本、系统资源(如硬盘、主板、设备等)。 Guid 保证是唯一的。(谢谢 ck!)我还没有见过

Guid g = new Guid.NewGuid();
Guid g = Guid.NewGuid(); /* Thanks Dave! */

在连续运行中 g 具有相同值的实例。

它更常用于互斥体,一个示例是创建应用程序的单个实例,并通过使用带有 guid 的互斥体来保证应用程序实例的生命周期。

甚至在某些情况下,它被用在数据库中,但使用它的方法却令人不悦。

A Guid is a unique number that has billions of permutations and is made up of a mixture of hexadecimal and numbers in groups. And it is generated based on the different factors, such as time, windows version, system resources such as hard disks, motherboards, devices and so on. A Guid is guaranteed to be unique. (Thanks ck!) I have not seen an instance where you do

Guid g = new Guid.NewGuid();
Guid g = Guid.NewGuid(); /* Thanks Dave! */

where g will have the same value in successive runs.

It is more commonly used for mutexes, an example would be to create a single instance of an application and by using a mutex with a guid guarantees the lifetime of the instance of the application.

Even, in some instances, it is used in the database but the method of using it is frowned upon.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文