【问题标题】:What are the chances of getting a duplicate when using SecureRandom.hex?使用 SecureRandom.hex 时出现重复的可能性有多大?
【发布时间】:2018-11-07 09:46:04
【问题描述】:

我计划使用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-rails ruby algorithm combinations probability


    【解决方案1】:

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

    16**32 = 340282366920938463463374607431768211456
    

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

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

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

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

    【讨论】:

    • 看生日悖论。可能值数量的平方根是对重复之前的预期样本数量的更好估计。这仍然不太可能,但不像您建议的那么不可能。
    【解决方案2】:

    由于它是一个以 16 为基数的数字系统,因此16 ** SecureRandom.hex.length 可能的变化非常多。

    如果您不想在用户数量增加时溢出堆栈,最好使用带有退出条件的循环。

    MAX_ATTEMPTS = 3 # For you to choose.
    
    def key
      MAX_ATTEMPTS.times do
        hex = SecureRandom.hex
        return hex unless Model.where(key: hex).exists?
      end
    
      fail 'No attempts to generate a key left.'
    end
    

    【讨论】:

      【解决方案3】:

      在您的设置中,键的长度似乎是 32。

      • 在三个执行中没有得到重复的机会是:

        ((16**32 - 1)/16**32) * ((16**32 - 2)/16**32)
        

        因此,在三个执行中某处获得(至少一对)重复的机会是:

        1 - ((16**32 - 1)/16**32) * ((16**32 - 2)/16**32)
        = 8.8162076e-39
        
      • 有:

        16**32 = 3.4028237e+38
        

        不同的字符串。

      • 您的方法可以在按预期工作时避免重复,但它也极有可能陷入永久状态并且永不终止。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-08
        • 2011-06-22
        • 2011-08-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多