私の同僚と私は、データベース内で識別するためのユーザー ID と投稿 ID を自動生成するために、次の方法のどれを使用するかについて議論しています。
1 つのオプションでは、Random のインスタンスを 1 つ使用し、いくつかの便利なパラメータを取得して、あらゆる種類の文字列生成ケース (つまり、4 桁の数値ピンから 20 桁の英数字 ID まで) に再利用できます。コードは次のとおりです。
// This is created once for the lifetime of the server instance
class RandomStringGenerator
{
public const string ALPHANUMERIC_CAPS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
public const string ALPHA_CAPS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public const string NUMERIC = "1234567890";
Random rand = new Random();
public string GetRandomString(int length, params char[] chars)
{
string s = "";
for (int i = 0; i < length; i++)
s += chars[rand.Next() % chars.Length];
return s;
}
}
もう一つの選択肢は、単に以下を使用することです:
Guid.NewGuid();
私たちはどちらもそれがGuid.NewGuid()
私たちのニーズに合うことはわかっていますが、私はむしろカスタム メソッドを使用したいと思います。同じことを行いますが、より制御性があります。
同僚は、カスタム メソッドは自分たちで作成したものなので、衝突が発生する可能性が高くなると考えています。Random の実装を完全に理解しているわけではないことは認めますが、Guid.NewGuid() と同様にランダムであると思われます。カスタム メソッドの一般的な使用法は次のようになります。
RandomStringGenerator stringGen = new RandomStringGenerator();
string id = stringGen.GetRandomString(20, RandomStringGenerator.ALPHANUMERIC_CAPS.ToCharArray());
編集1:
- キーを生成するための自動増分 (または同様の) 機能を持たない Azure テーブルを使用しています。
- ここでの回答の中には、NewGuid() を使用するように指示するものもあります。「それがその目的だから」です。Guid と同じ自由度がある場合、作り上げられたメソッドの方が衝突を生成する可能性が高くなる理由について、より詳細な理由を探しています。
編集2:
また、セッショントークンとは異なり、ウェブサイトのURLに表示するために見た目を良くする必要がある投稿IDを生成するために、独自の方法を使用していました(http://mywebsite.com/14983336) なので、ここではガイドはオプションではありませんが、それでも衝突は回避する必要があります。
ベストアンサー1
私は、Guid と同じ自由度が与えられた場合に、作り上げられたメソッドが衝突を生成する可能性が高くなる理由について、より詳細な理由を探しています。
まず、他の人が指摘しているように、Random
スレッドセーフではありません。複数のスレッドから使用すると、内部データ構造が破損し、常に同じシーケンスが生成される可能性があります。
2番目は、Random
現在の時刻に基づいてシードされます。Random
同じミリ秒内に2つのインスタンスが作成されます(1ミリ秒は数ミリ秒です)。百万複数の CPU サイクル (最新のハードウェアで 1 回の試行で 100 万回) は同じシードを持つため、同じシーケンスが生成されます。
3番目に、私は嘘をつきました。Random
現在の時刻に基づいてシードされるのではなく、マシンが稼働していた時間シードは 32 ビットの数値で、粒度はミリ秒単位なので、ラップアラウンドするまでに数週間しかかかりません。しかし、問題はそこではありません。そのインスタンスを作成する時間帯は、Random
マシンの起動後数分以内である可能性が非常に高くなります。マシンの電源を入れ直すたび、またはクラスター内で新しいマシンをオンラインにするたびに、ランダムのインスタンスが作成される小さなウィンドウが開きます。このインスタンスが頻繁に作成されるほど、以前と同じシードが取得される可能性が高くなります。
(更新: .NET フレームワークの新しいバージョンでは、これらの問題の一部が軽減されています。これらのバージョンでは、Random
同じミリ秒内に作成されたすべてのシードが同じになることはなくなりました。ただし、 にはまだ多くの問題がありますRandom
。これは疑似ランダムであり、暗号強度のランダムではないことを常に覚えておいてください。Random
は実際には非常に予測可能なので、予測不可能なことに依存している場合は適していません。)
他の人が言っているように、データベースに主キーが必要な場合はデータベースに主キーを生成させる; データベースに任せましょう。グローバルに一意の識別子が必要な場合は、ガイドを使用する; それが彼らの目的です。
最後に、GUID の使用法と悪用についてさらに詳しく知りたい場合は、私の「GUID ガイド」シリーズを読んでみてください。パート 1 はここにあります。