首页 > 解决方案 > 使用 SecureRandom.hex 时出现重复的可能性有多大?

问题描述

我打算用它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"

我得到重复结果的可能性有多大?

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

def generate_string
  string = SecureRandom.hex

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

  string
end

unique_string = generate_string

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

而且,由于我没有得到重复,我可以用多少个字符串来生成SecureRandom.hex组合,然后才能生成?

标签: ruby-on-railsrubyalgorithmcombinationsprobability

解决方案


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

16**32 = 340282366920938463463374607431768211456

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

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

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

tl;博士重复的机会非常低。只有key数据库中列上的唯一索引才能确保永远不会有任何重复(因为竞争条件或绕过此方法生成的键)。


推荐阅读