十分大きな乱数をユニークな識別子として使うのがなぜ安全なのか

いろいろなソフトウェアで、大きいランダムな値をユニークな値とみなすということが行われている。例えばユニークな識別子としてよく使われるUUIDはただの122ビットの乱数だ。gitもSHA-1ハッシュ値が160ビットの乱数のように扱えることを期待して、それをユニークな識別子として使っていた。実際にはランダムな2つの値が同じになる確率はゼロではないのに、なぜこれが安全なやり方だと言えるのだろうか? それについてちょっと説明してみよう。

あるシステムが、乱数で生成された識別子の衝突のなさに依存しているとして、仮に衝突が発生した場合、相当悪い結果、例えば復旧不可能な形でデータベースが壊れてしまうとしよう。これはどれくらい危険なのだろうか?

数学の問題で、学校のクラスの中で同じ誕生日の人が1組以上いる可能性は思ったより高いという話を聞いたことがあると思う。あるランダムに生成された値が衝突する確率というのは、この誕生日問題と同じ方法で計算することができる。

Wikipediaに概算式が載っているのでそれを適用して計算してみると、128ビット乱数を825兆個生成したとき、衝突している乱数が10億分の1の確率で存在するということになる。825兆個の128ビット乱数というのはそれを保存するだけでディスクが1.3エクサバイト必要になるという、とても大きな数だ。逆に言うと現実的なほとんどすべてのシステムで、128ビットの乱数が衝突する確率は10億分の1よりずっと小さい。

どんな頑強なシステムでも壊れる確率はゼロではない。地球規模の最悪のシナリオの一つとして、恐竜を絶滅させたレベルの隕石衝突がおよそ10億年に1度あるとすると、来年そのような隕石が地球にぶつかる確率は10億分の1だ。したがって128ビット乱数の衝突のなさに依存しているシステムで、乱数が衝突してシステムが復旧不可能になるリスクというのは、来年巨大隕石が地球に衝突して何もかもが終わるリスクよりずっと低いということになる。つまり、乱数のビット数が十分に大きくて、それが本当にランダムなら、衝突の可能性を心配するのは天が落ちてくるのを替わりに心配したほうがマシなくらい杞憂なのだ。

この記事が気に入ったらサポートをしてみませんか?