何気ない記録

なんとなく自分の意見を書き記すときにつかいます。つまり不定期更新です。

そもそも多くの場合で目的と手段が間違っていると思うのだが

 

10秒で衝突するUUIDの作り方 - Speaker Deck

この例示の問題点はそもそもUUIDの生成ロジックがヤバいのと、乱数の発生自体の方法も誤用というダブルのミスを前提としている点。いないとは言わないがおそらくこのレベルの人は別言語でもやらかす人かと思われる。

メルセンヌツイスタはそんなに衝突しない - Qiita

細かい点は除いて同意。というか多くの場合乱数とUUIDには本来なんら関係がないのだがなぜかUUIDをランダムに生成したがる人が多いのが問題。値の連続性を秘匿したいのであればそれは暗号化の論点でありUUIDとは関係ない

 

この話、そもそも以前から疑問に思っている処理として、UUIDの生成に乱数を用いる人がそこそこいるわけですが、まずUUIDは乱数と関係はありません。

生成ルールの選択は、生成・利用環境に依存しており、並列環境で利用する場合は当然ですが生成ルールの選択する時点で善し悪しを選ぶべきなんですよ。

で、特定の情報や環境に依存するのであれば、当然その生成ルールは採用できないと実装前にわかるはずなんですが、なぜか人はネットの情報をそのままコピペするので「ランダムなIDを生成するならUUID」という勘違いをしてしまうわけです。

 

私が経験したケースで言えば、多くのUUIDの目的は、一意なIDを生成したいが連続性のあるIDをそのまま使用したくないというようなケースであったわけですが、それはUUIDでも代用できるものの、目的としてはシリアル値の秘匿化でしかないわけです。

 

で、そのケースでいえば、それは内部的にシリアル値であるべきで、これは衝突する事はありません(但し、疑似乱数同様に生成方法を誤れば別ですが)。

その上で、生成されたシリアル値を可逆でも非可逆でもよいのですが、秘匿化すればいいだけの話しであり、そういったライブラリも普通に存在します。

 

つまり、そもそも無理に適さない選択をする必要もないし、使い慣れない疑似乱数を使う必要もないケースが多数なわけです。

 

当然、有効桁数/有効文字数が有限である限り、仮にシリアル値を秘匿化したとしても結果的に衝突する事はさけられません。

例えば、秘匿化の手段としてハッシュ化を用いたとすると、ハッシュ化のアルゴリズムに依存した割合で衝突のリスクを負います。有名な事例で言えばgithubのようなサービスでもこの手の手法で衝突した云々の話はありましたから、秘匿化の方法を選択する時点でそのリスクは十分に検討すべきですが、それほど神経質にならなくて良い場合が多いでしょう。

逆に決して衝突したくないような要件(例えば、内部的なシリアル値を変更または欠番のような処理ができないようなケース)であれば、多くの場合で可逆のアルゴリズムを利用すれば衝突を避ける事が可能です。

 

当然単純に「UUIDなんだから衝突する事自体がおかしい」という話しはあるわけですが、目的の為に選択する手段が正しいか、またその利用方法は正しいのか、という事を確認できる限りはこの手の話しは多くの場合で問題を回避できます。

 

もっとも、元の記事主もはっきりと「結論:UUID生成はライブラリを使え自分で書くな」と仰っているように、今回のケースに限れば意図的に衝突させる事を目的とした話しですから、ライブラリを用いる事である程度回避可能ですが、それでも衝突するか否かは結局UUIDのバージョン選択やその生成アルゴリズムが自分の環境に適しているかという点を正しく判断できないと、ライブラリを用いても普通に衝突します。

 

ですので、それ本当にUUIDとすべきなのか?という点も含め、設計・実装段階で適切な判断を行う事が大事で、それ以上でもそれ以下でもない話しかと。