我正在开发一个每天生成大约 20 亿 个唯一 UUID 的系统。 UUID 是在客户端使用 JavaScript\Flash (AS3) 生成的。
我们最近注意到我们的 UUID 几乎是唯一的。我们有大约 20% (!) 的日常重复,其中大部分(相对于流量)来自 chrome。
我做了some reading and learned that the pseudo-random大多数浏览器(尤其是 Chrome)上的 PRNG 算法实现存在缺陷。 Chromium 和 Node.js 使用 V8 javaScript 引擎,该引擎实现了一种称为 MWC1616 的算法。
理论上,使用良好的 PRNG 生成的 UUID 应该具有 2132 probability对于碰撞,但对于 MWC1616,在一些非常现实的场景下,这个概率约为 1:30000。
为了解决这个问题,我考虑了以下选项:
- 在服务器上生成 ID(使用 Go)
- 通过使用 UUID 散列 IP、UA、时间戳等信息,在客户端生成更强的 ID。
- 用更好的随机生成器替换 Math.random()。
因为我更喜欢把东西放在客户端上,我不想重新发明轮子和修改 UUID 创建逻辑,所以我想坚持使用选项 3。
好消息是在较新的浏览器上,有 getRandomValues接口(interface)。不幸的是,我需要支持旧版浏览器。
所以我的问题是:
- 什么是好的和可靠的 JavaScript polyfill
crypto.getRandomValues()
(内部不使用 Math.random)?
AS3 Math.random() 是否使用浏览器的 Math.random()?它本身实现了相同的算法吗?
flash.crypto.generateRandomBytes() 是否使用 Math.random()?它使用 crypto.getRandomValues() 吗?如果不是,它实现了哪种算法?对于 AS3 中的同一问题,它会是一个很好的解决方案吗?如果没有,您会推荐哪个 AS3 加密库?
附言我强烈推荐我提到的文章-1- -2- -3- .多年来我一直意识到 Math.random() 的问题,但这篇文章真正让我明白了。
最佳答案
在花了一个多星期的时间对此进行研究之后 - 我的结论是:永远不要在客户端上生成 UUID。只是不要。特别是如果您打算扩展。
多年来,我知道浏览器的 Math.random 实现很糟糕,但直到我们达到每天数十亿事件的规模,我才明白它有多糟糕。
我决定采用最简单的技术解决方案并将 UUID 生成移至服务器。重复 ID 的百分比从每天 ~25% 下降到 ~0.0008%。
附言我们的服务器是用 Go 实现的。 Node.js 使用 JavaScript V8 引擎并且可能有同样的问题。虽然看起来如果您使用的是最新的 Node.js,您应该没问题。
关于javascript - 在 JavaScript 和 AS3 中生成真正唯一的 UUID - PRNG 和底层算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42809128/