Ruby SecureRandom 生成内容的唯一性?

huacnlee · 2012年08月07日 · 最后由 windstill 回复于 2013年11月16日 · 14069 次阅读
SecureRandom.hex
=> "93dcf2eb24591d8846f6a9ec804eceff" 
SecureRandom.random_number
 => 0.2754022060318716 
SecureRandom.urlsafe_base64
 => "xCHCIA7qpCYJwBBFiddUTg"
SecureRandom.uuid
 => "a79b9a7a-2f1f-4dc1-a0f1-8136b9f919ac"

http://rubydoc.info/stdlib/securerandom/1.9.2/SecureRandom

从文档上面看来,似乎只有 uuid 方法是绝对唯一的,其他几个文档上面没说,不知道是否唯一,有人知道么?

匿名 #1 2012年08月07日

uuid 是不是都是 36 位,如果是的,(小写字母 + 大写字母 + 10 个数字 + 横杠) 的数量,再 36 次方,这个数量还是有限的,怎么保证唯一呢

文档里不是告诉你,看 RFC 4122 了么

http://tools.ietf.org/html/rfc4122#section-4.4

理论上就是不保证唯一的

UUID 有一个生成算法是用计算机的网卡的 mac 地址作为 seed,因为网卡出厂前就由厂家的厂牌和批次号等手段确保了世界上每块网卡的 mac 地址不会重复,所以这种 UUID 可以被认为是安全的。但是在一般系统上取得 mac 的地址可能需要特殊的用户权限,所以这个方法不太流行。

理论上随机生成的 UUID 是有可能重复的,但是重复的概率小到了几乎不可能,所以是非常安全的。 http://en.wikipedia.org/wiki/UUID#Random%5FUUID%5Fprobability%5Fof%5Fduplicates

To put these numbers into perspective, one's annual risk of being hit by a meteorite is estimated to be one chance in 17 billion,[34] that means the probability is about 0.00000000006 (6 × 10−11), equivalent to the odds of creating a few tens of trillions of UUIDs in a year and having one duplicate. 

根据 rails tutorial 上面说的,这个概率是小到了多少多少分之一。重复了算你运气好。不过再加个时间戳应该很安全了

如果重复到了请立刻去买彩票。:P

UUID 又名 GUID

理论上有重复的可能性, 但是这个可能性非常地低, 低到,通常情况下,可以忽略不计。

细节如下:

GUID 在空间上和时间上具有唯一性, 保证同一时间不同地方产生的数字不同。 世界上的任何两台计算机都不会生成重复的 GUID 值。

由以下几部分的组合: 1 当前日期和时间,UUID 的第一个部分与时间有关,如果你在生成一个 UUID 之后,过几秒又生成一个 UUID,则第一个部分不同,其余相同。 2 时钟序列。 3 全局唯一的 IEEE 机器识别号,如果有网卡,从网卡 MAC 地址获得,没有网卡以其他方式获得。

http://baike.baidu.com/view/1052579.htm http://baike.baidu.com/view/185358.htm

以前做 MIS 系统,当数据库的记录,需要一个全局唯一标识的时候,就用 GUID。 这个情况尤其适用于,多个数据库的数据进行合并的时候。 ID 只能保证记录在一个数据库中唯一,但是不能保证在其他数据库中也唯一。

还有 C++ 的 Com 接口,也需要一个 GUID。 Windows 注册表中,全都是这些东西。

如果相同了的再重新生成一次

#8 楼 @hysios 有时候,无法验证该序号已经被使用。

@ery 这样的情况并不多

#10 楼 @hysios 呵呵 让我想起了 2 8 理论

@ery 那到不是这个意思,如果一定要不能重复又不能认证,建议用 uuid,但一般生成的 id 都会存储起来,以用来验证的

#12 楼 @hysios “但一般生成的 id 都会存储起来,以用来验证的” 我没明白你的意思.... 这个 id 是指 UUID 还是 传统的数据库 ID? “以用来验证的”验证什么,唯一性吗?

128 位的可以,32 位的不够,最多能映射 4G,有一定重复概率。128 位足够大,如果算法分布均匀的话,产生碰撞的可能性微乎其微。

我是用来作为上传文件名的

#15 楼 @huacnlee 上传文件名的话,用 userid + fileid + timestamp 取 sha1 就能解决唯一性了。

#16 楼 @ashchan 哦对呀,我搞晕,钻牛角尖了 之前是为了防止不同服务器同一时刻产生同名文件(用 timestamp)

#6 楼 @ery SecureRandom.uuid 生成的 uuid 是纯粹的随机生成的,不包含 MAC 地址,时间戳等有意的信息

The version 4 UUID is purely random (except the version). It doesn’t contain meaningful information such as MAC address, time, etc.

需要 登录 后方可回复, 如果你还没有账号请 注册新账号