設計の一部として UUID の使用を本当に強制されるのはどのような場合ですか?

StackOverflow https://stackoverflow.com/questions/703035

  •  22-08-2019
  •  | 
  •  

質問

本当に意味が分かりません UUID. 。衝突の確率はわかっていますが、 事実上ゼロ, 、 しかし 事実上ゼロ 不可能に近いものではありません。

誰かがUUIDを使用するしかない例を示してもらえますか?私がこれまで見てきたすべての使用例から、UUID を使用しない代替設計がわかります。確かに設計はもう少し複雑になるかもしれませんが、少なくとも失敗する可能性がゼロではありません。

私にとって UUID はグローバル変数のような気がします。グローバル変数を使用して設計を簡素化する方法はたくさんありますが、それは単に怠惰な設計にすぎません。

役に立ちましたか?

解決

私は、RubyのためのUUIDジェネレータ/パーサを書いたので、私は自分自身が合理的に被写体に十分な情報であると考えています。四大UUIDのバージョンがあります:

バージョン4つのUUIDは、本質的にランダムのわずか16バイトは、いくつかのUUIDバージョンおよびバリアントを同定するために、ビットいじると、暗号的に安全な乱数発生器から引き出されます。これらは、衝突する可能性は極めて低いですが、PRNGが使用されている場合、それが起こる可能性がまたはあなたが本当に、本当に、本当に、本当に、本当に悪い運を持って起こる場合。

バージョン5とバージョン3のUUIDは、UUIDを生成するために既に一意のデータの一部で名前空間を組み合わせるために、それぞれSHA1およびMD5ハッシュ関数を使用します。これは、たとえば、あなたはURLからUUIDを生成することができます。基本となるハッシュ関数にも衝突を持っている場合は、ここに衝突のみ可能です。

バージョン1つのUUIDが最も一般的です。彼らは(偽装されていない限り、一意である必要があります)ネットワークカードのMACアドレスを使用し、プラスタイムスタンプ、プラス通常のビットいじるUUIDを生成します。 MACアドレスを持っていないマシンの場合には、6つのノードバイトは暗号的に安全な乱数発生器で生成されます。 2つのUUIDは、タイムスタンプが以前のUUIDと一致していることを十分に速く順番に生成された場合、タイムスタンプは、以下のいずれかの発生しない限り発生しません1.衝突によってインクリメントさ:MACアドレスが偽装されています。二つの異なるUUID生成アプリケーションを実行しているマシンがまったく同じ瞬間にUUIDを生成し;ネットワークカードなしで、またはMACアドレスにユーザレベルのアクセスせずに二マシンが同じランダムノード列が与えられ、そして正確に同じ瞬間にUUIDを生成しています。私たちは、ゼロに戻ってタイムスタンプとロールオーバーを表現するためにバイトを使い果たしています。

現実的には、これらのイベントはいずれも、単一のアプリケーションのID空間内の事故によって発生しません。あなたは、インターネット全体の規模、たとえば、上のIDを受け入れている場合を除き、または悪意のある個人がIDの衝突の場合に悪い何かを行うことができるかもしれない信頼できない環境で、それはちょうどあなたが心配すべきものではありません。それはあなたが、私がそうであるように同じバージョン4 UUIDを生成するために起こる場合は、ほとんどの場合、それは問題ではないことを理解することが重要です。私はあなたとは全く異なるID空間でIDを生成しました。衝突は重要ではありませんので、私のアプリケーションは、衝突について知っていることはありません。あなたも、バージョン4 UUIDで、衝突を持って前に率直に言って、悪質な俳優のない単一のアプリケーション空間で、地球上のすべての生命の絶滅は、あなたが毎秒かなりの数のUUIDを生成している場合でも、長く発生します。

また、2 ^ 64 * 16は256エクサバイトです。あなたは、単一のアプリケーション空間でのIDの衝突の50%のチャンスがあった前と同じように、あなたはIDの価値は256エクサバイトを保存する必要があります。

他のヒント

UUID で購入できるのは、それ以外の方法では非常に難しいことですが、それは一意の識別子を取得することです。 中央当局との相談や調整を必要とせずに. 。何らかの管理されたインフラストラクチャなしでそのようなものを取得できるという一般的な問題は、UUID によって解決されます。

誕生日のパラドックスによれば、2^64 個の UUID が生成されると、UUID の衝突が発生する確率は 50% になると読みました。2^64 はかなり大きな数ですが、50% の衝突の可能性は危険すぎるように思えます (たとえば、5% の衝突の可能性が存在する前に、いくつの UUID が存在する必要があります。これでも確率が大きすぎるように思えます)。 。

この分析には 2 つの問題があります。

  1. UUID は完全にランダムではありません。UUID の主要なコンポーネントは時間ベースまたは場所ベースです。したがって、実際に衝突が起こる可能性を高めるには、衝突する UUID が異なる UUID ジェネレータからまったく同時に生成される必要があります。複数の UUID が同時に生成される可能性は十分にありますが、この非常に小さな UUID セット間の衝突の可能性をほぼ不可能にする他の問題 (位置情報やランダム ビットなど) が十分にあると思います。 。

  2. 厳密に言えば、UUID は、比較される他の UUID のセットの中で一意であればよいだけです。データベース キーとして使用する UUID を生成している場合、邪悪な代替世界のどこかで同じ UUID が COM インターフェイスの識別に使用されているかどうかは問題ではありません。アルファ・ケンタウリに「マイケル・バー」という名前の別の誰か(または何か)がいたとしても混乱は生じないのと同じです。

すべてが失敗の非ゼロのチャンスがあります。私は問題を発生する可能性がはるかに集中でしょう(つまり、あなたが考えることができるほとんど何でも)のUUIDの衝突より

「合理的」か、あなたは、「効果的に」それを置くように重点を置い:現実の世界がどのように動作するかを十分に良いです。 「実質的にユニーク」と「真にユニークな」間のギャップをカバーするにかかわる計算作業の量は膨大です。一意性は、収穫逓減の曲線です。その曲線上のいくつかの時点では、まだそこに手頃な価格であるところ、「十分にユニークな」間の線で、その後、我々曲線非常に急勾配。より多くの一意性を追加するコストが非常に大きくなります。無限一意性は無限のコストを持っています。

UUID / GUIDは、比較的、の合理の汎用一意であると想定することができるIDを生成するための計算が迅速かつ簡単に言えば、あります。これは、以前に接続されていないシステムからのデータを統合する必要がある多くのシステムでは非常に重要です。たとえば、次の2つの異なるプラットフォーム上で動作するコンテンツ管理システムを持っていますが、いくつかの点で他にあるシステムからコンテンツをインポートする必要がある場合。システムAからのデータとの間に、あなたの参照がそのまま残っていますが、システムB. A UUIDで作成したデータを任意の衝突を望んでいないので、あなたは、IDは変更したくない、これを解決します。

UUIDを作成するために絶対に必要なことはありません。それぞれが衝突の非常に低い確率で何かの鍵を生成することができますのオフラインのユーザーの標準を持っている、しかし、便利です。

これは、データベースのレプリケーションの解決などに役立てることができます...

これは、ユーザーがオーバーヘッドや衝突の可能性のない何かのためのユニークなキーを生成するために、のオンラインのために簡単だろうが、それはのUUIDがのためにあるものではありません。

とにかく、ウィキペディアから撮影した衝突の確率の単語、:

  

大局的にこれらの数字を配置するには、のいずれかの年間リスクがヒットしています   隕石は170億、同等で1回のチャンスと推定されることにより、   年のUUIDの兆の数十を作るのオッズにと   1つの重複を持ちます。言い換えれば、唯一の10億を生成した後   次の100年、作成の確率のためのUUID毎秒   ただ一つの重複は約50%になります。

あなたの体の中のすべての粒子が椅子を通して同時にトンネルあなたが上に座っているし、あなたは突然、自分が床に座っています。

という非ゼロの確率もあります

あなたはそれを心配しますか?

あなたは2つのデータベース間で複製されたときに古典的な例です。

DB(A)は、int型のID 10を有するレコードを挿入すると同時に、DB(B)はID 10内のレコードを作成し、この衝突です。

それらが一致しないので、

のUUIDでは、これは発生しません。 (ほぼ確実に)

私はUUIDを回避するための仕組みを持っています。どこかのサーバーを設定し、それを持っているソフトウェアのいくつかの作品は、普遍的に一意の識別子を望んでいるたびに、彼らはそのサーバーに連絡するように、それは1つのアウトを渡します。シンプル!

私たちはあからさまな悪意を無視した場合でも、これでいくつかの本当の実用上の問題があることを除いて。具体的には、そのサーバーが失敗したり、インターネットの一部から到達不能になることができます。サーバーの障害に対処するレプリケーションを必要とし、それが権利を取得するために、ののは非常に困難です(合意形成が厄介である理由のためにPaxosアルゴリズムに関する文献を参照)、あまりにもかなり遅いです。すべてのサーバーが「ネットの特定の部分からアクセスできない場合、彼らはすべての新規のIDを待っているだろうので、また、なしのそのサブネットに接続しているクライアントの何かをすることができるようになります。

だから... ...それは地球の存続期間中に失敗することはほとんどありません、または(ファンドと)が展開PITAになるだろうと頻繁に障害を持っている主要なインフラストラクチャを構築し、それらを生成するために、単純な確率的アルゴリズムを使用しています。私はのために行くだろうどれ知っています。

あなただけの、例えば選択肢を見れば簡単なデータベースアプリケーションのために、あなたは新しいオブジェクトを作成する前に、データベースを毎回照会する必要が、あなたはすぐにUUIDを使用すると、効果的にあなたのシステムの複雑さに減らすことができることがわかります。確かに - あなたはint型のキーを使用する場合はインクルードは、128ビットのUUIDの四半期に格納する32ビット、です。確かに - UUID生成アルゴリズムは、単に数をインクリメントするよりも多くの計算能力を取ります。しかし、 - 誰が気に?あなたの意図した一意のIDスペースに応じて、桁違いにそれを上回る簡単そうでないユニークな番号を割り当てる「権威」を管理するのオーバーヘッドます。

UUID==怠惰なデザインについて

喧嘩を売るという意見には私は同意しません。UUID の重複が統計的に不可能であり、数学的に証明されているのであれば、心配する必要はありません。小規模な N UUID 生成システムの設計に時間を費やすのは現実的ではありません。システムを改善できる方法は他にもたくさんあります。

私は、衝突の可能性についてのすべての話を得ることはありません。私は、衝突を気にしないでください。でも、私はパフォーマンスを気に。

https://dba.stackexchange.com/a/119129/33649

  

UUIDが非常に大きなテーブルのパフォーマンスの災害です。 (200K行があります   "非常に大きい" ではない。)

     CHAR(36) - CHARCTER・セットがUTF8の場合は、

あなたの#3は本当に悪いです   108バイトを占有!

     

のUUID(GUIDは)非常に "ランダム" です。 UNIQUEまたはいずれかとしてそれらを使用します   大きなテーブルの主キーは非常に非効率的です。のためです   テーブル/インデックスの周りに新しいUUIDを挿入するたびにジャンプすること   またはUUIDでSELECT。テーブル/インデックスは、キャッシュに収まらないほど大きい場合   (RAMよりも小さくなければならないinnodb_buffer_pool_sizeを参照してください、   典型的には70%)、「次の」UUIDが遅いディスクしたがって、キャッシュされなくてもよいです   ヒット。テーブル/インデックスは、キャッシュと同じ大きさの20倍、わずか1/20のとき   あなたがI / Oバウンドです。

- ヒット(5%)がキャッシュされます。      

だから、UUIDを使用していない場合を除きいずれか

     

あなたは「小さい」のテーブルを持っている、またはあなたが本当にために生成するのでそれらを必要とします   独特の異なる場所からのIDS(および別の方法を考え出したていません   それをするために)。 UUIDの詳細: http://mysql.rjweb.org/doc.php/uuid(それ   標準的な36-チャーのUUIDとの間で変換するための機能を含みます   BINARY(16)。)

     

UNIQUE AUTO_INCREMENTと同じでUNIQUE UUIDの両方を有します   テーブルには、廃棄物である。

     INSERTが発生した場合は、

、すべてのプライマリ/ユニークキーがためにチェックする必要があります   重複。どちらの一意のキーは、InnoDBの要件のために十分です   PRIMARY KEYを持ちます。 BINARY(16)(16バイト)は、幾分かさばります(   それPK)作りに対する引数が、それは悪くありません。嵩高   問題あなたは二次キーを持っています。 InnoDBは黙ってPKを鋲   各二次キーの最後へ。ここでの主な教訓はにあります   特に非常に大きいため、二次キーの数を最小限に抑えます   テーブル。比較ですのために:INT UNSIGNEDの範囲を持つ4バイトで0..4   10億。 BIGINTは8バイトである。

私の最後の仕事で、私たちは、一意UUIDで同定された第三者からオブジェクトを取得しました。私はUUID->長整数のルックアップテーブルに置くと、それは仕方速くそのようだったので、私の主キーとして長整数を使用します。

ミリ秒あたり10の未満のUUIDが同じMACアドレスから生成された制約下不可能衝突があると思われるバージョン1アルゴリズムを使用して

  

概念的には、元の(バージョン1)   UUIDの生成スキームはしたこと   とUUIDのバージョンを連結   あるコンピュータのMACアドレス   UUIDを生成し、と   100ナノ秒間隔の数   グレゴリオ暦の採択以来、   西のカレンダー。実際には、   実際のアルゴリズムはより複雑です。   このスキームを批判されています   それは十分に「不透明」ではないということ。   それはアイデンティティの両方を明らかに   UUIDを生成するコンピュータと、   それはそのようにしたした時点ます。

私はそれがどのように動作するか誤解場合誰かが私を修正

彼らはのためのUUIDが悪いデザインであることを言ったものに(いくつかの途方もなく小さな確率で)の可能性あなたのDBは、キーが...あなたが知ることができません生成された一方で、ヒューマンエラーの可能性が原因と衝突しますあなたのDB上の衝突があるため、いくつかの非予見必要性の鍵を生成FAR FAR FAR高いUUID4の衝突の可能性よりもです。私たちは、の知っているのDBは、それが再び1にIDSを開始します再作成し、された場合にどのように私たちの多くは、私たちは私たちが今までに必要ないだろう確信していたときに、テーブルを再作成しなければならなかったということ?ものは未知の未知の任意の日と間違って行くを開始したとき、私はUUIDの安全性に私のお金を入れたいです。

別にあなたがUUIDを要求し、他の誰かのAPIを使用する必要が例から、もちろん常に別の解決策があります。しかし、これらの選択肢はUUIDには行うのすべてのの問題を解決するのだろうか? 、それぞれが異なる問題を解決するために、あなたがハッキングのより多くの層を追加することになります、ときに一度それらのすべてを解決しているだろうか?

はい、のUUIDが衝突するために理論的には可能です。他の人が指摘したように、それは検討する価値だけではありませんポイントに途方もなくそうです。これは、これまでに起こったことはありませんし、最も可能性は決しています。それを忘れています。

の衝突を避けるために、最も「明白な」方法は、単一のサーバーは明らかに深刻なパフォーマンスの問題を作成し、まったくオフライン世代の問題を解決していないすべての挿入、上のユニークなIDを生成させることです。おっとます。

他の「明白な」ソリューションは、UUID V1は、(IEEE OUIを経由して)発電機のMACアドレスを使用して何をするか、本質的である、事前に独特の数字のブロックを手中央機関です。しかし、実際には、これははるかに可能性が高いUUID V4の衝突よりもあるように、MACアドレスは、最終的にはすべてのために中央当局のネジをアップ起こるのか重複します。おっとます。

UUIDを使用に対する最善の引数は、彼らが「大きすぎる」だということですが、(かなり)小さいスキームは必然的に最も興味深い問題を解決するために失敗します。 UUIDがサイズは、これらの非常に問題を解決でその有用性の固有の副作用です。

それはあなたの問題はのUUIDが提供するものを必要とするのに十分な大きさではなく、その場合には、何か他のものを使用して自由に感じることができます。あなたの問題は(そしてほとんどがそう)が突然大きくなった場合でも、後で切り替え終わるだろう - と、最初の場所でそれらを使用していないためにあなた自身を蹴ります。なぜ失敗したデザインではなく、成功のために設計するのも簡単だ?

彼らはキットの異なる部分を介して配布することができるスーパーグローバル変数であるため、

UUIDが、グローバル変数、唯一の悪いことに関連した悪いコーディングプラクティスのすべてを体現します。

は最近、正確な代替モデルとプリンタの置き換えで、このような問題を押すと、クライアントソフトウェアのいずれも動作しないだろうことがわかりました。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top