質問

次のシナリオの場合:

1データベース 4台のWebサーバー

Webサーバーは、データベースの一意のIDをどのように生成して一意にするのですか?はい、自動インクリメントを使用することは可能ですが、これは簡単にクロール/推測/などされます。そのため、現在、自動インクリメントはオプションではありません。

役に立ちましたか?

解決

UUIDを使用( http://www.ietf.org/rfc/rfc4122.txt )。衝突は起こりそうにないため、新しいUUIDを再生成することで発生した場合に対処できます。または、各サーバーの一意のID(macアドレスなど)を連結することで防止できます。-

StringBuilder sb = new StringBuilder(UUID.randomUUID());
InetAddress address = InetAddress.getLocalHost();
String uid = sb.append(NetworkInterface.getByInetAddress(address).getHardwareAddress());

他のヒント

UUIDを使用できます:

import java.util.UUID;        

UUID uuid = UUID.randomUUID();
System.out.println(uuid.toString());

衝突が本当に心配な場合は、キーを事前に生成し、一意のインデックスを使用してデータベーステーブルに保存できます。次に、ダウンタイム中にテーブルにデータを入力し、使用されたキーを時々削除/アーカイブする定期的なジョブを用意します。

使用しているDBシステムは何ですか?アプリはどのサーバーがリクエストを行っているかを知っていますか? DBにキーを決定させますか、それともコードで設定しますか?

キーを要求したサーバーを示すプレフィックスまたは2番目のフィールドを持つ自動インクリメントを使用するのと同じくらい簡単です。

自動インクリメントまたはシーケンスが受け入れられない理由はわかりません。内部IDを「推測可能」にしたくないですか?これはアカウント番号のようなもので、誰かに有効なアカウント番号を推測させたくないのですか?

さて、さて、すでに述べたUUIDのほかに、2つの明白な可能性が思い浮かびます。

  1. シーケンスを使用してから乱数を生成し、2つの異なるシーケンス番号が同じ最終番号を与えることができないようにアルゴリズムを使用して、2つの組み合わせからアカウント番号を作成します。たとえば、次の単純なアルゴリズムは次のようになります。次のシーケンス番号を取得し、12345678を掛け、0〜12345678-1の乱数を生成し、2つを加算します。

  2. 最後に割り当てられた番号を保持するレコードを1つ持つデータベース上のテーブルを作成します。新しい番号が必要になるたびに、このレコードをロックし、前の値を使用して次の値を生成し、レコードを更新します。数値が常に増加する限り、重複しないことが保証されます。

サーバーの識別子を識別子の一部として使用するスキームがある場合は、その識別子を単に構成ファイルのどこかに格納された番号にしないことをお勧めします。私は現在、誰かが各サーバーに「サーバーID」を与えるという素晴らしいアイデアを持ったシステムに取り組んでいます。これは、IDを記録するために組み込まれています。サーバーIDは、手動で割り当てられる小さな整数です。サーバーが3つしかない本番環境ではそれほど難しくありません。しかし、開発とテストでは、常に新しいサーバーが起動および停止し、テスト構成ファイルが絶えず放り投げられているため、管理するのは苦痛です。サーバーID期間を使用することは避けますが、使用する場合は、中央サーバーによって自動的に割り当てられるようにするか、IPまたは安全なものから派生させます。

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