如何在C#中生成GUID?
kzmpq1sx1#
a really good article on Raymond Chen's blog描述了GUID是如何生成的,特别是为什么guid的子字符串不能保证是唯一的。基本上,一个a/a是使用以下组合生成的:
*用于生成GUID的机器的MAC地址(因此在不同机器上生成的GUID是唯一的,除非MAC地址被重用)*时间戳(因此在同一台机器上不同时间生成的GUID是唯一的)*额外的“紧急统一器位”(这些用于确保在同一台机器上几乎完全相同的时间生成的GUID是唯一的)*算法的标识符(因此使用不同算法生成的GUID是唯一的)
然而,这只是用于生成GUID的一种特定算法(尽管我相信它是.NET框架使用的算法),并且不是the one used by the .NET framework。
lp0sw83n2#
该算法在此记录为Globally unique identifier
anauzrmj3#
最初的问题:GUID如何生成其标识符??如果我使用下面的代码Guid g = Guid.NewGuid(),它的输出是什么?输出是数字和数字的组合,还是只有数字???.Net System.Guid只是一个128位整数(16字节)。数字和字母与此无关。您可以使用ToString()方法查看Guid的各种“人类可读”版本,其中包括数字0-9和字母A-F(表示十六进制值),但这完全取决于您希望如何输出它。
System.Guid
ycggw6v24#
除了RFC中提到的“随机16字节”之外,还有其他形式的随机数。一些微软产品(例如SQL Server)可以选择性地生成这些“顺序GUID”,这些GUID基于“系统中第一个网卡的MAC地址+基于系统时间的不断增加的计数器”的组合。这些“顺序GUID”具有一个很好的特性,即当用作聚集索引的数据库主键时,总是将新记录追加到数据库表的“末尾”。这有助于防止数据库索引碎片和页拆分。如果使用随机GUID作为具有聚集索引的数据库主键,则从物理分配的Angular 来看,新记录将随机插入表的“中间”,这会导致索引碎片和随着时间的推移部分满的数据库页。使用顺序GUID仍然允许您在多个系统上独立地生成GUID,并且确信不会有任何冲突(如果不为每个系统分配“范围”或不同的种子和增量,则使用顺序整数作为主键将无法获得此属性,这在大型分布式应用程序中是管理噩梦)。
cx6n0qe35#
这取决于。对于Unix中的.NET Core,GUID是通过创建一个128位的随机数并执行几个位操作来生成的。在.NET Core for Windows和.NET framework中,它会对Windows函数UuidCreate进行远程过程调用(因此它们的生成方式完全取决于您的Windows版本)。对于Unix和最新版本的Windows,您会注意到有一个十六进制数字始终是4。这是因为它是Uuid 4的版本号,这意味着它们是用随机字节生成的。GUID通常是用时间戳和MAC地址之类的东西生成的,但这成为了一个攻击媒介,因为它告诉最终用户有关系统的信息,并帮助他们更容易预测未来的GUID。
h9a6wy2h6#
关于Wikipedia和MSDN的详细信息。简而言之,整数是一个随机的128位整数,但我们使用十六进制数字对其进行格式化,以便它们易于阅读(这就是您看到的8-4-4-4-12格式)。至于它是如何产生的,请参阅链接的维基百科文章。
7uhlpewt7#
这些碎片的分解过程是这样的:
总共128位。
o4hqfura8#
我们可以直接根据生成的GUID检查这一点。我更喜欢一些源文件,但TBH的维基百科纲要是相当不错的。第一个相关部分是关于可移植性变体。摘要:为了确定MySQL类型,我们必须查看变体和可能的版本。
变体由第9个八位字节的初始位表示。它是通过将初始位“固定”到0、10、110或111来完成的。使用
0
10
110
111
string show(Guid g) => $"{g}: fam {Convert.ToString(g.ToByteArray()[8], 2)}"; show(Guid.NewGuid())
我们可能得到"1b579ecd-b72c-4550-b10b-f8dd41699ac1: fam 10110001"。该系列固定到10、OSF DCE UUID或变体2。这个变体定义了一个版本,保存在第7个八位字节的更有效的“半字节”中。但是,有一个复杂的因素:编码中的字节序。这些基于MS的节以 little-endian 格式存储。一起来看看吧:用另一种快速的方法
"1b579ecd-b72c-4550-b10b-f8dd41699ac1: fam 10110001"
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以突出显示版本:
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。不客气
"154573de-d420-433b-bb25-aff50590038b: fam 10111011, ver 43"
4
2ic8powd9#
GUID是一个唯一的数字,它有数十亿个排列,由十六进制和数字组合而成。它是基于不同的因素生成的,如时间,Windows版本,系统资源,如硬盘,主板,设备等。Guid保证是唯一的。谢谢CK!我还没见过你这样做的例子
Guid g = new Guid.NewGuid(); Guid g = Guid.NewGuid(); /* Thanks Dave! */
其中g在连续运行中具有相同的值。它更常用于互斥,例如创建应用程序的单个示例,并通过使用带有guid的互斥来保证应用程序示例的生命周期。甚至,在某些情况下,它在数据库中使用,但使用它的方法是不受欢迎的。
g
9条答案
按热度按时间kzmpq1sx1#
a really good article on Raymond Chen's blog描述了GUID是如何生成的,特别是为什么guid的子字符串不能保证是唯一的。
基本上,一个a/a是使用以下组合生成的:
*用于生成GUID的机器的MAC地址(因此在不同机器上生成的GUID是唯一的,除非MAC地址被重用)
*时间戳(因此在同一台机器上不同时间生成的GUID是唯一的)
*额外的“紧急统一器位”(这些用于确保在同一台机器上几乎完全相同的时间生成的GUID是唯一的)
*算法的标识符(因此使用不同算法生成的GUID是唯一的)
然而,这只是用于生成GUID的一种特定算法(尽管我相信它是.NET框架使用的算法),并且不是the one used by the .NET framework。
lp0sw83n2#
该算法在此记录为Globally unique identifier
anauzrmj3#
最初的问题:
GUID如何生成其标识符??如果我使用下面的代码Guid g = Guid.NewGuid(),它的输出是什么?
输出是数字和数字的组合,还是只有数字???
.Net
System.Guid
只是一个128位整数(16字节)。数字和字母与此无关。您可以使用ToString()方法查看Guid的各种“人类可读”版本,其中包括数字0-9和字母A-F(表示十六进制值),但这完全取决于您希望如何输出它。ycggw6v24#
除了RFC中提到的“随机16字节”之外,还有其他形式的随机数。一些微软产品(例如SQL Server)可以选择性地生成这些“顺序GUID”,这些GUID基于“系统中第一个网卡的MAC地址+基于系统时间的不断增加的计数器”的组合。
这些“顺序GUID”具有一个很好的特性,即当用作聚集索引的数据库主键时,总是将新记录追加到数据库表的“末尾”。这有助于防止数据库索引碎片和页拆分。
如果使用随机GUID作为具有聚集索引的数据库主键,则从物理分配的Angular 来看,新记录将随机插入表的“中间”,这会导致索引碎片和随着时间的推移部分满的数据库页。
使用顺序GUID仍然允许您在多个系统上独立地生成GUID,并且确信不会有任何冲突(如果不为每个系统分配“范围”或不同的种子和增量,则使用顺序整数作为主键将无法获得此属性,这在大型分布式应用程序中是管理噩梦)。
cx6n0qe35#
这取决于。对于Unix中的.NET Core,GUID是通过创建一个128位的随机数并执行几个位操作来生成的。在.NET Core for Windows和.NET framework中,它会对Windows函数UuidCreate进行远程过程调用(因此它们的生成方式完全取决于您的Windows版本)。对于Unix和最新版本的Windows,您会注意到有一个十六进制数字始终是4。这是因为它是Uuid 4的版本号,这意味着它们是用随机字节生成的。GUID通常是用时间戳和MAC地址之类的东西生成的,但这成为了一个攻击媒介,因为它告诉最终用户有关系统的信息,并帮助他们更容易预测未来的GUID。
h9a6wy2h6#
关于Wikipedia和MSDN的详细信息。
简而言之,整数是一个随机的128位整数,但我们使用十六进制数字对其进行格式化,以便它们易于阅读(这就是您看到的8-4-4-4-12格式)。至于它是如何产生的,请参阅链接的维基百科文章。
7uhlpewt7#
这些碎片的分解过程是这样的:
总共128位。
o4hqfura8#
我们可以直接根据生成的GUID检查这一点。我更喜欢一些源文件,但TBH的维基百科纲要是相当不错的。第一个相关部分是关于可移植性变体。摘要:为了确定MySQL类型,我们必须查看变体和可能的版本。
. NET生成的GUID是哪个变体(& version)?
变体由第9个八位字节的初始位表示。它是通过将初始位“固定”到
0
、10
、110
或111
来完成的。使用我们可能得到
"1b579ecd-b72c-4550-b10b-f8dd41699ac1: fam 10110001"
。该系列固定到10
、OSF DCE UUID或变体2。这个变体定义了一个版本,保存在第7个八位字节的更有效的“半字节”中。但是,有一个复杂的因素:编码中的字节序。这些基于MS的节以 little-endian 格式存储。一起来看看吧:用另一种快速的方法
我们会看到这样的结果
前三组是转置的,因为每组都是一个完整的整数(两个用于时间,一个保留; 32、16和16位)。最后两组不是,因为最后8个八位字节是一个“字符串”:1个保留的八位字节(其中表示“家族”)和7个“节点”八位字节。
因此,第7个版本的八位字节实际上被编码为第8个(索引7)。展开
show
以突出显示版本:我们会得到
"154573de-d420-433b-bb25-aff50590038b: fam 10111011, ver 43"
。问题中的半字节是4
,因此版本4:伪随机生成。正如你在上面的例子中看到的,变体2版本显示为第三组的第一个十六进制字符。你会注意到在.NET GUID中,它总是4。在阅读了这篇文章之后,你永远不会 * 不 * 寻找那4。
不客气
2ic8powd9#
GUID是一个唯一的数字,它有数十亿个排列,由十六进制和数字组合而成。它是基于不同的因素生成的,如时间,Windows版本,系统资源,如硬盘,主板,设备等。Guid保证是唯一的。谢谢CK!我还没见过你这样做的例子
其中
g
在连续运行中具有相同的值。它更常用于互斥,例如创建应用程序的单个示例,并通过使用带有guid的互斥来保证应用程序示例的生命周期。
甚至,在某些情况下,它在数据库中使用,但使用它的方法是不受欢迎的。