使用 SecureRandom.hex 时获得重复的机会有多大?

Dav*_*ulo 0 ruby algorithm combinations ruby-on-rails probability

我计划使用它SecureRandom.hex为我的用户生成 API 密钥。

到目前为止,这是 3 次执行的输出:

Loading development environment (Rails 5.2.1)
2.3.5 :001 > SecureRandom.hex
 => "0369e9b7c6ffa07bd8d0a263f7b4cfa6" 
2.3.5 :002 > SecureRandom.hex
 => "1a8a168d7f70676451e3d59353e22693" 
2.3.5 :003 > SecureRandom.hex
 => "94cc188e9e5c3abfe587510fa79993ce"
Run Code Online (Sandbox Code Playgroud)

我获得重复结果的机会有多大?

我创建的这个方法真的能避免产生重复的内容吗?

def generate_string
  string = SecureRandom.hex

  generate_string if Model.where(:key => string).count > 0

  string
end

unique_string = generate_string
Run Code Online (Sandbox Code Playgroud)

我正在使用递归,如果字符串已经存储在数据库中,它只会生成另一个字符串。

而且,由于我没有得到重复的字符串,在用完可SecureRandom.hex生成的组合之前我可以生成多少个字符串?

spi*_*ann 5

在您的示例中(使用SecureRandom.hex默认长度 32 时)有

16**32 = 340282366920938463463374607431768211456
Run Code Online (Sandbox Code Playgroud)

可能有不同的十六进制值。这意味着有机会1:340282366920938463463374607431768211456创建副本。这种可能性非常低,恕我直言,对此过于担心并没有多大意义。

当您打算将该键存储在数据库中时,我建议向该数据库列添加唯一索引,以确保(在数据库级别)不可能存储任何重复项。

此外,您还询问您的示例代码是否足以避免重复。答案是。由于概率很低,这是高度理论化的,但是您可能会遇到竞争条件,其中两个作业同时生成相同的密钥,检查数据库中是否没有这样的密钥并且两个作业都存储相同的密钥值写入表中。

tl;dr 重复的可能性极低。只有数据库中列上的唯一索引key才能确保永远不会出现任何重复项(因为竞争条件或绕过此方法生成的键)。