データを複数の物理データベースに分割する場合、
グローバルに一意の識別子をサポートすることは簡単な作業ではなくなりました。
私は可能なオプションをまとめ、それらの長所と短所を考慮しようとしました。
キーにはどのような要件(一意性以外)を提示できますか?
キーは単調に増加するはずですこれが必要な理由:
- 自動自然ソート(時系列を含む)
- ランダムキーよりも高速な挿入
上記は、ツリーを使用するインデックスにのみ関連します。
キーはクライアント側で作成する必要がありますこれが必要な理由:
- 一意のキーはオブジェクトが保存される前でも既知であるため、アプリケーションはすぐに目的のシャード(クラスターノード)に切り替えることができます
- アプリケーションは、複数の関連オブジェクトを一度に(1つのトランザクションまたはバッチジョブで)保存できます。
キーサイズの制限(例:64ビットのみ)これが必要な理由:
- 場合によっては、128ビットまたは160ビットの識別子が問題になることがあります。 たとえば、Sphinx検索は整数ドキュメント識別子(64ビットバージョンでは64ビット)のみをサポートします。
- 32ビットまたは64ビットのキーを持つインデックスは、理論的には、任意の長さのキーを使用するよりも速く動作するはずです。
- 32ビットまたは64ビットのキーを持つインデックスはよりコンパクトであり、その結果、メモリに完全に収まります(大量のデータに関連)。
一意のキーを生成する方法は何ですか?
アプリケーション側のID生成(UUIDなど)UUIDを使用すると、すべてが比較的簡単になります。ライブラリを取得し、アプリケーション側でキーを生成します。 UUIDは多くのシステムで広く使用されています。 値は、衝突が不可能になるように形成されます。
短所:•標準UUIDの長さは128ビットです(実際、32バイトの16進数の文字列として直接保存することがよくあります)
•通常、UUIDはキーの自然なソートを提供しません
鍵生成のための別個のサービスこのオプションは、たとえば
Flickや
Twitterで使用されます。
短所:•追加コンポーネントの導入によるシステムの複雑化
•潜在的に単一障害点、またはキージェネレータの高可用性を確保するための追加の努力が必要
値の範囲によるデータベース側の自動インクリメント値の範囲全体がサブ範囲に分割され、各シャード(クラスターノード)が独自の範囲を担当します。次に例を示します。
1-0 .. 3FFFFFFF、
2-40,000,000 .. 7FFFFFFF、
3-80000000 .. BFFFFFFF、
4-C0000000 .. FFFFFFFF
短所:•データベースは自動インクリメントをサポートする必要があります(多くのNoSQLストレージには適用されません)
自然なソートはできません
•クライアントは、オブジェクトを挿入する前にキーを「知らない」。 キーを見つけるには、別のリクエストを行う必要があります。
•クラスタノードの数を増やすことはほとんど不可能です。
Instagramの自動インクリメントこの決定は、
Instgramチーム(写真共有アプリケーション)の技術ブログで
説明されています。
データベース(PostgreSQL)の側で生成され、ビットフィールドで構成される64ビットキーを使用します
63 31 0 |======|======|======|======|======|======|======|======| | CUSTOM TIMESTAMP | SHARD ID | AUTO |
どこで
-
CUSTOM TIMESTAMP
タイム
CUSTOM TIMESTAMP
(41ビット)-2011-01-01 00:00:00からのミリ秒単位の時間
SHARD ID
(13ビット)-論理パーティション識別子(シャードの数は物理ノードの数よりも大きい)
AUTO
(10ビット)-論理パーティション内で一意のシーケンス(シーケンス)(シャード)
長所(範囲にわたる自動インクリメントと比較):•自動時系列ソート
また、どのようなオプションを知っており、使用していますか?