Slide 1

Slide 1 text

今だから言える 『UUIDは本当に一意を保証 してくれるのか?』 疑ってました

Slide 2

Slide 2 text

自己紹介 ・名前 朽方邦孝 ・所属 フューチャーアーキテクト 金融サービス事業部 ・得意な言語 SQL

Slide 3

Slide 3 text

UUIDとは 出典: IT用語辞典 e-Words 一意? (・。・;

Slide 4

Slide 4 text

UUIDとは 出典:https://securesamba.com/term/uuid/ 一意じゃないの? (・。・;

Slide 5

Slide 5 text

UUIDとシーケンスの違い UUID 数値シーケンス サンプル 0aebf1c2fd8811eb849800059a3c7a00 1,2,3,4~等 順序 ランダム(連番にはならない) 連続 その他 IDを推測し難い 連番のためIDが推測しやすい データサイズ ※ 16BYTE(=128bit / 8) ⇒DBに入れるとINDEXが重い 2BYTE(1から32767) 4BYTE(1から2147483647) 8BYTE(1から9223372036854775807) マスタ 存在しない 必要(1箇所で管理) 同時実行 可 (どのサーバ上でも生成可能) 不可 (マスタがあるサーバでのみ生成可、複数箇 所で利用される場合は順番待ちでボトルネック になりやすい) ※ postgreSQLのカラムサイズの場合

Slide 6

Slide 6 text

ITエンジニア風に説明すると ● 1BITで、0/1の2通りを記録可能 ● 128BITで、2^128通り記録可能 ● この128bitに一定のアルゴリズム(後述)で0/1をセットしたものがUUID

Slide 7

Slide 7 text

身近なもので例えると ● 1円玉を裏表適当に一直線に128枚並べる、この128枚1セットが1UUID ● 128枚セットを延々とランダムに並べ続け、 全く同じ並び順がでる確率が、UUIDが衝突する確率 ● 組み合わせは2^128 =340,282,366,920,938,000,000,000,000,000,000,000,000 340澗2823溝6692穣938𥝱 340兆の1兆倍 まったくピンと来ないけれど

Slide 8

Slide 8 text

UUIDで同じ値が発生する確率(128bit) ● 50%弱の確率で衝突が発生するのに、必要な試行回数 ○ 2^(128/2)=18,446,744,073,709,600,000 1844京6744兆0737億960万 出典: https://ja.wikipedia.org/wiki/誕生日攻撃 2600億回試行で 0.0000000000000001% (10^-18)

Slide 9

Slide 9 text

【参考】めったに発生しないもの 確率 備考 落雷(死亡) 0.0001% 2014年米国(25人/260万人) 航空機(死亡) 0.000034% 米国の飛行機に1回搭乗し墜落する確率 宝くじ 0.00001% 2021サマージャンボ宝くじ(1/1000万)

Slide 10

Slide 10 text

UUIDがバカでかい値なのはわ かったけど どういう仕組みで一意なの?

Slide 11

Slide 11 text

UUIDのバージョン Ver 生成値 一意性 1 60bit:タイムスタンプ(1/10億秒単位) 14bit:クロックシーケンス 48bit:ノード(MACアドレス、または乱数) 理論的には衝突し得る 2 28bit:タイムスタンプ 6bit:クロックシーケンス 40bit:ローカルID/ローカルドメイン 48bit:ノード 理論的には衝突し得る (DCEシステムにおける権限認可 を目的に設計されたもの、システ ム開発では使用しない) 3/5 122bit:ユニークな名前(URL等)をハッシュ関数で変換 インプットが一意であれば担保 4 122bit:乱数 理論的には衝突し得る ※4bitはバージョン、2bitはバリアントを表す

Slide 12

Slide 12 text

UUID Ver1の衝突検証 (チート有り)

Slide 13

Slide 13 text

UUID Ver1のデータ構成 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 11010101011101011010100100010100111111001111100000010001111010111010010100110101000000000000010110011010001111000111101000000000 11010101011101011010100100010101111111001111100000010001111010111010010100110110000000000000010110011010001111000111101000000000 11010101011101011010100100010110111111001111100000010001111010111010010100110111000000000000010110011010001111000111101000000000 11010101011101011010100100010111111111001111100000010001111010111010010100111000000000000000010110011010001111000111101000000000 11010101011101011010100100011000111111001111100000010001111010111010010100111001000000000000010110011010001111000111101000000000 11010101011101011010100100011001111111001111100000010001111010111010010100111010000000000000010110011010001111000111101000000000 11010101011101011010100100011010111111001111100000010001111010111010010100111011000000000000010110011010001111000111101000000000 11010101011101011010100100011011111111001111100000010001111010111010010100111100000000000000010110011010001111000111101000000000 11010101011101011010100100011100111111001111100000010001111010111010010100111101000000000000010110011010001111000111101000000000 48 ノード(MACアドレス) 32 タイムスタンプ 下位 2+14 クロック シーケンス 4 ver 16 タイムスタンプ 中位 12 タイムスタンプ 上位 同一サーバで実行する 場合は同値 シーケンス、+1する 2^14=16384回で0に戻る 0.0000000001秒単位で保持 (上記以上の間隔で生成すると必ず一意)

Slide 14

Slide 14 text

つまり、同一サーバ上で 1/10億秒以内に 16385回以上生成すると 100%ID衝突が発生

Slide 15

Slide 15 text

(スーパーコンピュータ並の演算能力さえあれば) 実現可能ですね (・∀・)

Slide 16

Slide 16 text

私のPCスペックでは 500,000/秒程度しか不可能な ので、今回はチートで時を止 めます (時刻取得が必ず固定値を返すように魔改造)

Slide 17

Slide 17 text

UUID Ver1の衝突実験 (0.0000000001秒で16385UUIDを生成できるサーバを使用した体) クロックシーケンスが1周し、同じ値が発生 ※DBはpostgreSQL13を使用

Slide 18

Slide 18 text

UUID Ver4の衝突検証

Slide 19

Slide 19 text

UUID Ver4のデータ構成 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 00001111100011100100010101001001100010110110100101000110001000111010010010100010010010110101001010111110011011010010100111011000 10011011111100011010010010111010011011111010101101001101010010101000000101101110111010010110101010110010101101000101100110010001 01100010101011100110101011101010111011110001010001001010011101101001101001101010001110111010001110011111001100101010111000101111 00000010010101101111100000011011000111111110100101001010000111011011101111100101111110010001010110111001111101101111100101011101 11010111110100110100010110010011110100100010010101000010101111011001001110111000000000100100100011001000011111001101110000011101 01110011110100010110100101000010110101101110001001001100111111101011111111011010100111000101000010000100010111101001000110011101 00000001111000110010011000010011001110010010011001000001100111001011100011110001011110110100101101010100010010101010011011111010 11111010000101001011110001101011110000100111011001000001000111001010100110100000010010000100111010011101010110010001010111101100 00100100100010001000010110101100110000110111111001000111011011101000010001010101011010001111111111101101101000111001011111110011 62 ランダム 2 var 4 ver 48 ランダム 12 ランダム 固定値:6bit ランダム:122bit

Slide 20

Slide 20 text

UUID Ver4で同じ値が発生する確率(122bit) ● 50%弱の確率で衝突が発生するのに、必要な試行回数 ○ 2^(122/2)=2,305,843,009,213,690,000 ○ 230京5843兆92億1369万 出典: https://ja.wikipedia.org/wiki/誕生日攻撃

Slide 21

Slide 21 text

UUID Ver4の衝突を観測するのに必要なDBサイズ 230京5843兆92億1369万レコード×46Byte(16Byte+レコード情報)※ =98,784,247,808GB =96,468,992TB =94,208PB =92EB ※DBはpostgreSQL13を使用 INDEXを含まない、凡そのサイズ INDEX含む場合はさらに倍程度必要 出典:情報通信白書平成26年版 全世界の 92EB

Slide 22

Slide 22 text

UUID Ver4の衝突を観測するのに必要なDB費用 230京件、92EBのデータを保持するには、 1DBサーバ(9646TB)×1万台が必要 1DBサーバ内に23万テーブル作成 (1テーブルに10億レコードを保持) 月120万$×1万台 ×3ヶ月※ =¥3,938,476,542,000 ≒4兆円 ※50万件/1secのペースで 1万台×64CPUで並列実行 超々ざっくりの適当な計算です <(_ _)>

Slide 23

Slide 23 text

UUIDを3000万件INSERT時の処理速度変化① (100万件毎のINSERT時間) 0 50 100 150 200 250 300 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 INDEX 有り INDEX 無し 単位(秒) 単位(100万件) 総レコード 件数 INDEX 有り INDEX 無し 1M 13.49 1.97 2M 12.28 1.91 3M 12.77 1.95 4M 14.61 1.97 5M 24.47 2.02 6M 33.86 2.44 7M 44.99 2.17 8M 42.92 2.24 9M 48.11 2.01 10M 57.6 2.38 11M 54.74 2.23 12M 59.61 2.3 13M 75.68 1.97 14M 76.19 2.6 15M 74.11 2.18 16M 62.93 2.11 17M 78.54 1.9 18M 76.34 1.93 19M 69.48 2.46 20M 77.47 2.24 21M 104.58 2.42 22M 112.26 2.29 23M 126.25 2.04 24M 130.18 2.21 25M 153.48 1.81 26M 198.14 1.94 27M 218.42 1.91 28M 225.18 2.79 29M 246.75 2.5 30M 235.41 2.7 単位(秒)

Slide 24

Slide 24 text

UUIDを3000万件INSERT時の処理速度変化② (3000万件INSERT完了までの累計時間) 単位(秒) 単位(100万件) 0 500 1000 1500 2000 2500 3000 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 INDEX有り INDEX無し 自分のノートPC内で3回 実施した平均値 ※環境・性能によって曲 線の傾きは変わります

Slide 25

Slide 25 text

まとめ ● V1 ○ 累計生成回数によらず衝突発生確率は一定 (タイムスタンプを含むため) ○ 衝突を発生させるにはスーパーコンピュータ並の性能が必要 ● V4 ○ 累計生成回数に応じて、衝突発生確率が指数関数的に上がる ○ 衝突発生確率が現実的な値になるほど、DBにデータを保持するのは、 物理的・処理性能的に困難(大幅な速度低下が見込まれる)

Slide 26

Slide 26 text

No content