一部で話題になったUUIDのv6/v7/v8のドラフトRFCですが、1年ほど前からGitHubでの議論に参加しています。日本人で首を突っ込んでる人はあまりいなさそうなので、現状について日本語でも少しまとめておきたいと思います

12
LiosK @LiosK

ITにちょっと強い経理屋さん

https://t.co/OD8e9iCtr2

LiosK @LiosK

一部で話題になったUUIDのv6/v7/v8のドラフトRFC ietf.org/archive/id/dra… ですが、1年ほど前からGitHubでの議論に参加しています。日本人で首を突っ込んでる人はあまりいなさそうなので、現状について日本語でも少しまとめておきたいと思います

2022-11-03 19:30:03
LiosK @LiosK

議論に参加したのは以前のドラフトを元にプロトタイプを実装したときにいくつかフィードバックを送ったのがきっかけで、以降1年間ほどの議論はだいたい追いかけています。逆に、それ以前の動きはあまり追えていません。議論自体は数年間続いているので、それ以前にもいろいろとあったと思います

2022-11-03 19:30:04
LiosK @LiosK

まずドラフトのステータスですが、以前日本語でも話題になった asnokaze.hatenablog.com/entry/2021/04/… の仕様が継続しています。当時は既存のRFC 4122をそのままにv6/v7/v8を別RFCで定義する方針でしたが、IETF 114以降、v1-v5も含む新しいRFCでRFC 4122を置き換える方針でworking groupが公式に立ち上がっています

2022-11-03 19:30:04
LiosK @LiosK

まだドラフト00で、以前のドラフトとRFC 4122をマージしたばかりなので、テキストはまだかなり動くと思われます。が、v6/v7/v8の仕様に関してはここ半年ぐらい動いていないので、多少は安定してきたのかもしれません。それ以前はかなり動いていて、特にv7は前述の記事時点から激変しています

2022-11-03 19:30:04
LiosK @LiosK

新ドラフトRFCではRFC 4122の誤謬を訂正しつつv6/v7/v8/Maxの4種類を追加し、さらに実装上の注意点をベストプラクティスとして詳細に論じています。128ビット固定の長さと8-4-4-4-12の16進文字列表現は、ひとまずは据え置かれています

2022-11-03 19:30:05
LiosK @LiosK

v6/v7は時系列順に生成されるUUIDで、今回の改定の主眼です。従来のUUIDはランダムな順で生成されるため、DBのキーとして挿入するとインデックスで使われるB-treeなどとの相性が悪く、これを解決するために時系列順のUUIDが待望されていました

2022-11-03 19:30:05
LiosK @LiosK

v6はv1のフィールドを並び替えることで時系列順としたものです。既存のv1実装を転用したり、v1値とラウンドトリップ変換する用途が想定されています。ただ、v1の1582年紀元100ナノ秒単位タイムスタンプは一般的でないので、v1のしがらみがなければ、Unixタイムスタンプベースのv7が推奨されています

2022-11-03 19:30:06
LiosK @LiosK

v7は48ビットのミリ秒Unixタイムスタンプと、予約ビットを除く74ビット乱数を組み合わせたものです。オプションで、ミリ秒以下の生成順を保証するための乱数初期化カウンターを使用することも認められています。v4とともに、今後の主流になると目されているバージョンです

2022-11-03 19:30:06
LiosK @LiosK

(v7) 当初は小数表現を使ってナノ秒やマイクロ秒タイムスタンプも混在させる案などもあったのですが、議論の末かなり単純化されました。予約ビットやカウンターの使い方は異なるものの、ULIDとほぼバイナリ互換の形になりました

2022-11-03 19:30:06
LiosK @LiosK

v8は予約ビットを正しく埋めればあとは自由というバージョンです。まったく新しいスキームのIDを使ったり、v7ベースだけど生成ノードIDを埋め込みたいとかの用途で使います。他のUUIDと混用するときにこれらが不正なUUIDとしてライブラリから弾かれたりすると辛いので、正式に定めている感じです

2022-11-03 19:30:07
LiosK @LiosK

(v8) 当初はカスタムタイムスタンプ用のバージョンとされたためドラフト00ではそんな記述も残っていますが、それらの制約は撤廃される見込みです。なお、v8のuniquenessは実装次第なので、uniquenessを当てにすべきではないとされています

2022-11-03 19:30:07
LiosK @LiosK

最後のMax UUIDは全ビットを1にしたUUIDで、全ビットを0にしたNil UUIDをビット反転したものです。具体的な用途やセマンティクスは仕様に書かれない予定ですが、番兵法の終端値に使うことなどが想定されています

2022-11-03 19:30:07
LiosK @LiosK

現時点で仕様に織り込まれているのは以上ですが、議論がまとまらず仕様に織り込まれなかった論点がいくつかあります。新しい文字列表現や可変長UUID、新バリアントなどです。これらは一旦棚上げされていますが、今後の動向次第では仕様に織り込まれるかもしれません

2022-11-03 19:30:08
LiosK @LiosK

従来の8-4-4-4-12形式の16進文字列表現は冗長なので、より短いエンコーディングの標準化が待望されています。ULIDのようにCrockford Base 32を使う案が出されましたが、Crockfordアルファベットの採用を正当化する根拠が不足していたり、ULIDのBase 32の計算方法がRFC 4648と異なることなどから難航

2022-11-03 19:30:08
LiosK @LiosK

さらにBase 36、58、62等のより複雑・高密度の方式やbookend approach ietf.org/archive/id/dra… なども俎上に上がることで収拾がつかなくなり、ひとまず棚上げされています。議論は続いているものの、低調です github.com/uuid6/new-uuid…

2022-11-03 19:30:08
LiosK @LiosK

文字列表現は、case-insensitiveでありながら128ビットを25字に短縮できるBase 36を個人的には推していますが、Base 32ほど実装が簡単でないため、あまり人気はありませんでした

2022-11-03 19:30:09
LiosK @LiosK

可変長UUIDも提案されました。用途によっては128ビットは大きすぎるので短縮したり、uniqueness確保のための追加エントロピーを付加するなどのニーズがありましたが、複雑化がペイするほどのユースケースが見つからず、かつ複数文字列表現への対応も難しくなるため、棚上げされました

2022-11-03 19:30:09
LiosK @LiosK

個人的には、128ビットを切ると乱数ベースでuniversally uniqueと言い切るのが難しくなり、中央で各生成ノードにIDを割り当てたりする必要があるので、UUIDの枠組みでIDを短縮するのは難しいと見ています。短縮IDの事例はInstagramのものが参考になります instagram-engineering.com/sharding-ids-a…

2022-11-03 19:30:09
LiosK @LiosK

現行UUIDは歴史的な事情によりバージョンとバリアントの予約ビットが入り組んでいてビット操作がうっとうしいため、いっそ新バリアント0b1110を定義してverとvar を1バイトにまとめようという提案もありました。が、そこまでラディカルな提案にはなかなか支持が集まらず、下火になりました

2022-11-03 19:30:10
LiosK @LiosK

以上です。最後になりますが、UUIDの議論に参加するかたわら、「ぼくのかんがえたさいきょうの128ビットID」を仕様化して各言語で実装していたりもします。もしよかったらお試しください github.com/scru128/spec

2022-11-03 19:30:10