在.NET中编写函数以根据种子生成GUID的最简单方法是什么?这样我才能对其唯一性有更大的信心?
string GenerateSeededGuid(int seed) { /* code here */ }
理想情况下,种子将来自CryptGenRandom,它描述了随机数生成如下:
此函数生成的数据是加密随机的。它是 比典型随机数生成的数据更随机 生成器,例如C编译器附带的生成器。
此函数通常用于生成随机初始化向量 和盐值。
软件随机数生成器的工作方式基本相同。 它们以随机数开头,称为种子,然后使用 算法根据它生成伪随机比特序列。 这个过程中最困难的部分是获得真正的种子 随机。这通常基于用户输入延迟或抖动 来自一个或多个硬件组件。
使用Microsoft CSP, CryptGenRandom 使用相同的随机数 其他安全组件使用的生成器。这允许很多 促进系统范围种子的过程。 CryptoAPI存储了一个 每个用户的中间随机种子。为了形成种子 随机数生成器,一个调用应用程序提供它可能的位 例如,鼠标或键盘定时输入 - 然后 结合存储的种子和各种系统数据和用户 进程ID和线程ID,系统时钟等数据 系统时间,系统计数器,内存状态,可用磁盘集群, 散列用户环境块。这个结果用于播种 伪随机数发生器(PRNG)。 [...]如果应用程序可以访问一个好的随机源,它可以 在调用之前用一些随机数据填充 pbBuffer 缓冲区 的 CryptGenRandom 即可。然后,CSP使用此数据进一步随机化其数据 内部种子。省略初始化的步骤是可以接受的 调用 CryptGenRandom 之前 pbBuffer 缓冲区。
答案 0 :(得分:13)
您在GenerateSeededGuid
方法中真正需要做的就是创建一个128位的随机数并将其转换为Guid。类似的东西:
public Guid GenerateSeededGuid(int seed)
{
var r = new Random(seed);
var guid = new byte[16];
r.NextBytes(guid);
return new Guid(guid);
}
答案 1 :(得分:13)
tldr; 使用Guid.NewGuid
而非尝试发明另一种“更随机”的方法。 (当我想要一个可预测的,可重置的序列时,我能想到从种子创建UUIDvX的唯一原因是。但是,GUID可能也不是最好的方法 2 。)
通过定义为有限范围 - 128位减去 6个版本控制位,所以122 bits of uniqueness for v4 - 只有只有(albeit supremely huge number! astronomically big!)“唯一”标识符。
由于Pigeonhole Principle,只有很多鸽笼。如果鸽子最终继续繁殖,每只鸽子的洞数就不够了。由于Birthday Paradox,假设完全随机,两只鸽子将在它们全部填满之前尝试争夺相同的鸽笼。因为没有Master Pigeonhole List 1 这是无法预防的。此外,并非所有动物都是鸽子 3 。
虽然there are no guarantees as to which GUID generator will be used,.NET使用底层OS调用,这是一个GUIDv4(又名随机UUID )生成器since Windows 2k。据我所知 - 或者非常关心 - 这对于这样的目的而言是随机的。 十多年已经过了很好的审查,而且还没有被替换。
来自维基百科:
..只有在接下来的100年中每秒生成10亿UUID后,创建一个重复的概率大约为50%。如果地球上的每个人拥有6亿UUID,那么一次重复的概率约为50%。
1 虽然仍然有一组有限的鸽笼,UUIDv1(又名 MAC UUID ) - 假设独特的时空 - 保证确定性生成唯一编号(在给定计算机上每秒生成一些“相对较小”的理论最大UUID数)。不同的鸽子生活在不同的平行维度 - 真棒!
2 Twitter uses Snowflakes在其自己的分布式唯一ID方案中的并行维度。
3 兔子喜欢住在Burrows,而不是Pigeonholes。 GUID的 use 也充当隐式并行分区。只有当重复的GUID 用于相同的目的时,才会出现与冲突相关的问题。想想有多少重复的自动增量数据库主键!
答案 2 :(得分:0)
public static Guid SeededGuid(int seed, Random random = null)
{
random ??= new Random(seed);
return Guid.Parse(string.Format("{0:X4}{1:X4}-{2:X4}-{3:X4}-{4:X4}-{5:X4}{6:X4}{7:X4}",
random.Next(0, 0xffff), random.Next(0, 0xffff),
random.Next(0, 0xffff),
random.Next(0, 0xffff) | 0x4000,
random.Next(0, 0x3fff) | 0x8000,
random.Next(0, 0xffff), random.Next(0, 0xffff), random.Next(0, 0xffff)));
}
//Example 1
SeededGuid("Test".GetHashCode());
SeededGuid("Test".GetHashCode());
//Example 2
var random = new Random("Test".GetHashCode());
SeededGuid("Test".GetHashCode(), random);
SeededGuid("Test".GetHashCode(), random);
此方法基于php v4 uui https://www.php.net/manual/en/function.uniqid.php#94959
答案 3 :(得分:-1)
这有点旧,但是不需要随机生成器。但是,是的,这对于测试目的很有用,但对于一般用途却不是
public static Guid GenerateSeededGuid<T>(T value)
{
byte[] bytes = new byte[16];
BitConverter.GetBytes(value.GetHashCode()).CopyTo(bytes, 0);
return new Guid(bytes);
}