我们观察到这组近 200,000 个 UUID 相隔两个月重播,我想知道是否有人见过类似的东西。
UUID 是使用 UUID.randomUUID() 生成的。 在深入研究这个问题(查看java源代码)时,randomUUID()在引擎盖下使用了SecureRandom(),而SecureRandom()又使用NativePRNG。 据我了解,NativePRNG 使用/dev/urandom 来获取其种子。 当然,这意味着令人困惑 - 不知何故,/dev/urandom 将相同的种子返回给 NativePRNG 两个月。 据我所知,一旦实例化,PRNG 就不会重新播种。 这是一个长时间运行的作业,它侦听消息并使用 UUID 作为它的 ID。 伪代码很简单:
< receive message>
String uuid = UUID.randomUUID().toString();
String fname = h.composeArtifact(uuid);
操作系统是 Centos 6,位于运行 JDK1.6 的 AWS EC2 实例上。 这是任何人过去见过/经历过的事情吗? 似乎是那种不应该"永远不会发生"的事情......
实际上,从 JDK 1.6 源代码中,UUID.randomUUID()
以java.util.SecureRandom
实例为源。如果你得到了一个重复的 UUID 序列,那么要么你非常幸运(或者非常不幸,取决于你的观点),要么有人玩过虚拟机快照,要么你的 Java 配置中有一些可疑的东西。
拍摄虚拟机快照时,您可以记录计算机、进程和 RAM 的完整实时状态(包括)。如果存在一个已实例化的 SecureRandom
实例的实时进程,则还原快照将恢复该状态,因此每次还原发生时,该SecureRandom
输出的随机值序列将相同,直到SecureRandom
从/dev/urandom
(/dev/urandom
不断收集"随机"物理事件)重新设定种子, 但在下一次重新播种之前,这些不会影响SecureRandom
状态)。
Java 配置可能会影响SecureRandom
,因为SecureRandom
不是 PRNG,而是围绕正式注册的加密提供程序提供的SecureRandomSpi
实例的 shell。Sun的JDK带有一个默认的实现,通常以系统的资源为源(在Linux上/dev/urandom
)。但是,这可以配置;查找 java.security.egd
系统属性,以及java.security
文件中的 securerandom.source
属性。默认提供程序也可以完全替换为执行不同操作(并且可能非常糟糕)的替代实现。有关一些详细信息,请参阅此答案。验证确实使用了哪个随机源可能有点复杂,但您可以尝试使用 strace 启动进程,这将显示系统调用,因此在某个时候是否打开了/dev/random
或/dev/urandom
。
如果您的 Java 配置很好,并且没有带有 VM 快照的游戏,并且您确定您确实获得了与以前相同的 UUID 序列,那么您真的应该购买强力球票(但我不诚实地相信这种情况)。