web-dev-qa-db-ja.com

randomUUIDは一意のIDを提供しますか?

REST APIのセッショントークンを作成しようとしています。ユーザーがログインするたびに、次の方法で新しいトークンを作成しています。

UUID token = UUID.randomUUID();
user.setSessionId(token.toString());
Sessions.INSTANCE.sessions.put(user.getName(), user.getSessionId());

ただし、sessionTokenの重複を防ぐ方法はわかりません。

例:user1がサインインしてトークン87955dc9-d2ca-4f79-b7c8-b0223a32532aを取得し、user2がサインインしてalsoがトークン87955dc9-d2ca-4f79-b7c8-b0223a32532aを取得するというシナリオはありますか。

これを行うより良い方法はありますか?

22
birdy

UUIDの衝突が発生した場合は、次に抽選に参加してください。

ウィキペディアから:

ランダムに生成されたUUIDには、122個のランダムビットがあります。合計128ビットのうち、バージョン(「ランダムに生成されたUUID」)には4ビットが使用され、バリアント(「Leach-Salz」)には2ビットが使用されます。

ランダムなUUIDを使用すると、確率論(誕生日パラドックス)を使用して、2つの値が同じになる確率を計算できます。近似を使用する

p(n)\approx 1-e^{-\tfrac{n^2}{{2x}}}

これらは、x = 2122でn個のUUIDを計算した後の偶発的な衝突の確率です。

n確率68,719,476,736 = 236 0.0000000000000004(4×10-16)2,199,023,255,552 = 241 0.0000000000004(4×10-13)70,368,744,177,664 = 246 0.0000000004(4×10-10)

これらの数値を考慮に入れると、隕石に当たる誰かの年間リスクは170億分の1の確率であると推定されます。これは、確率が約0.00000000006(6×10−11)であることを意味します。 1年で数十兆を超えるUUIDがあり、1つが重複しています。つまり、次の100年間、毎秒10億個のUUIDを生成した後にのみ、複製が1つだけ作成される確率は約50%になります。地球上のすべての人が6億のUUIDを所有している場合、1つの重複の確率は約50%になります。

53
Tom G

UUIDのサイズは有限であるため、すべての空間と時間にわたって一意である方法はありません。

妥当なユースケース内で一意であることが保証されているUUIDが必要な場合は、Log4j 2のUuid.getTimeBasedUuid()を使用できます。 1ミリ秒あたり10,000未満のUUIDを生成する限り、約8,900年間は一意であることが保証されています。

7
rgoers

Oracle UUIDドキュメント。 http://docs.Oracle.com/javase/7/docs/api/Java/util/UUID.html

彼らは、Internet Engineering Task Forceのこのアルゴリズムを使用しています。 http://www.ietf.org/rfc/rfc4122.txt

要約からの引用。

UUIDは128ビット長であり、空間と時間にわたって一意性を保証できます。

アブストラクトは保証を主張していますが、3.4 x 10^38の組み合わせ。 CodeChimp

6
SethB