分散システム向けに Snowflake ID を生成する
Snowflake ID(Twitter 発)は、タイムスタンプ、マシン ID、シーケンス番号を組み合わせ、調整なしで分散システム内の一意なソート可能 ID を作り出します。
- 1
Snowflake は 64 ビット ID です:41 ビットのタイムスタンプ(エポックからのミリ秒、約 69 年)、10 ビットのマシン ID(1024 台)、12 ビットのシーケンス(1 台あたり 1 ミリ秒に 4096 ID)。これにより、マシン間の調整なしに、時間順にソートされた毎秒約 400 万 ID を生成できます。Twitter、Discord、Instagram で使われています。マシン ID はジェネレータごとに一意でなければなりません。ZooKeeper、Etcd、マシン ID サービスで割り当ててください。
- 2 タイムスタンプコンバーター →
Snowflake の時間コンポーネント用に、現在のミリ秒タイムスタンプを取得します。タイムスタンプは、41 ビットの範囲を最大化するため、カスタムエポック(Unix エポックではない)からのミリ秒にしてください。例えばエポック 2020-01-01 なら約 69 年分の ID が得られます。タイムスタンプが時間順序と時間にわたる一意性を提供します。
- 3 高精度計算ツール →
コンポーネントを結合します:id = (timestamp << 22) | (machineId << 12) | sequence。ビットシフトが各コンポーネントの位置を決めます。ビット幅を検証してください:タイムスタンプ(41 ビット)+マシン ID(10 ビット)+シーケンス(12 ビット)= 64 ビット。シーケンスは 1 ミリ秒内で増分し、タイムスタンプが進むとリセットされます。
- 4 UUID / ULID ジェネレーター →
比較のために UUID を生成します。Snowflake は 64 ビット(8 バイト、BIGINT に収まる)、UUID は 128 ビット(16 バイト)。Snowflake は時間でソート可能、UUID は不可。Snowflake はマシン ID の調整が必要、UUID は不要。高スループットの分散システムには Snowflake を、より単純なシステムや調整が不可能な場合は UUID を使ってください。
よくある質問
- 一意のマシン ID はどう割り当てますか?
- 選択肢:(1) ZooKeeper/Etcd — ID を原子的に取得し、シャットダウンで解放。(2) 設定ファイル — 各サーバーに手動で ID を割り当て。(3) IP アドレスのハッシュ — マシンの IP を 10 ビット ID にハッシュ(衝突リスクあり)。(4) クラウドメタデータ — AWS/GCP のインスタンス ID を使用。(5) データベースシーケンス — 原子的に増分。マシン ID は一意でなければなりません。重複は ID 衝突を引き起こします。
- タイムスタンプがオーバーフローするとどうなりますか?
- カスタムエポックから約 69 年後、41 ビットのタイムスタンプがオーバーフローします。ID が折り返され、ソート可能性が壊れ、衝突が起こる可能性があります。エポックはデプロイ日に近づけて計画してください。限界に近づいたら、新しいエポックに移行してください(ID 生成全体の更新が必要ですが、既存の ID には影響しません)。