1

65535 より大きい整数値を ushort にパックするためのシステムを考案しようとしています。説明させてください。

SQL Server の IDENTITY 列を使用して Int32 値を生成するシステムがあり、Int32 ID を ushort にオーバーフローさせる運用中のクライアント API によって制限されています。幸いなことに、クライアントには、これらの ID を持つものの約 20 程度のインスタンス (パッケージと呼びましょう) しかなく、ローカルの兄弟間でそれらを一意にする必要があるだけです。一般的に受け入れられている解決策は、クライアントに送信する前に Int32 ID を ushort に変換することです (キャストではなく、変換を意味します)。ただし、このアプローチには問題があります。

  1. 65535 未満の一部の ID は、有効期限が切れていないため、任意の時点で特定のクライアントで引き続き有効である可能性があります。
  2. ID の衝突は発生しません。つまり、パッケージ ID 1 がクライアントに送信された場合、65536 に適用されたときに ushort を作成するために Int32 から 65535 が削除された回数を追跡するアルゴリズムも 1 になり、衝突が発生します。
  3. 返されたときに、ushort を Int32 に再構築できる必要があります。

この問題を解決するために利用できるのは、エコーされる単一の符号付きバイト フィールドであり、127 の値で遊ぶことができます (0 ~ 9 を別の目的で使用しているため、実際には 117 です)。これを「バイトフィールド」と呼びます。

3 つの異なる翻訳ルーチンについて説明しました。

  1. 乗法: ushort を作成するために Int32 から 65535 を削除した回数をバイト フィールドに格納します。これには、上で詳述した衝突の問題があります。
  2. シリアル化されたセッション状態: クライアントごとに、そのクライアントに関する事実に基づいてセッション ID を生成します。次に、クライアントがサーバーに再度アクセスしたときに、パッケージのインベントリを既知のデータベース ID に変換できるように、1 から配信されたパッケージの数までの 1:1 変換テーブルを保存します。シリアル化されたセッション状態をデータベースにバックアップし、1 秒間に数百から数千のトランザクションをサポートしたいため、これにはオーバーヘッドの問題があります。
  3. バイト フィールドが、Int32 を受け取り、それを ushort に変換する変換アルゴリズムの ID である、さまざまなアルゴリズム アプローチ。明らかに、これらの多くは単純な乗法 (変換できる ID の上限を増やすため) になりますが、いくつかは、より小さな境界 (32768 など) を使用して、数値を加算/減算して、数値にできるだけ近づける乗法でなければなりません。兄弟間で一意であることを保証できる番号。このアプローチはプロセッサを集中的に使用しますが、スケーラビリティを維持しながら衝突を回避できるようにする必要があります (ただし、このアプローチでは、アップグレードにより ushort の問題が自然に解消される前に上限に達することはありません)。

したがって、私の質問は次のとおりです:上記の私のアプローチよりも良い方法はありますか?そうでない場合は、特定の数値がより大きい場合に1〜65535の数値を生成するアルゴリズム(アプローチ#3の場合)に関して何を探す必要がありますか? 0 で、一方向ハッシュであってはなりませんか?

明確化: ushort の上限が最大の問題というわけではありません。クライアント API が ushort を使用しているため、クライアントのバイト フィールドを組み合わせてより大きな値を取得することはできません (クライアント API はアップグレードできませんが、最終的には存在しなくなります) )。

4

3 に答える 3

1

他にもいくつかのオプションを考えることができます:

データベース内のエントリは全体で 65536 未満ですか? その場合、セッション状態に関連付けられていないが、アプリケーションの永続的な部分であるマッピング テーブルを維持できます。

インデックスのエントリの大半は、たとえば 50,000 未満ですか? その場合は、そのような値を直接マップし、セッションに関連付けられたマップを残りの値に使用できます。

このようなセッション データの永続化が問題であり、クライアントの数がかなり少ない場合は、クライアント/セッション アフィニティを有効にして、マップをサーバーに対してローカルに維持することができます。

Web アプリケーションでない場合は、クライアント自体でマップを維持できます。

衝突を回避するアルゴリズム的な方法は見当たりません - 衝突する例をいつでも思いつくことができると思います。

于 2008-09-23T20:13:46.993 に答える
1

アプローチ2について:

2 番目のアプローチは、NAT がどのように機能するかです。ローカル ネットワーク上のすべての TCP/UDP クライアントには、最大 65535 個のポート (ポート 0 を除く) とプライベート IP が使用されています。ルーターは、単一のパブリック IP しか認識していません。2 つのクライアントが両方とも送信元ポート 300 を持っている可能性があるため、プライベート IP をパブリック IP に単純に置き換えることはできず、衝突が発生します。したがって、IP を置き換え、ポートを「変換」します (NAT: Network Address Translation)。返されると、パッケージを転送する前に、ポートを元に変換し、パブリック IP をプライベート IP に再度置き換えます。あなたはそれ以外に何もしていないでしょう。ただし、ルーターはその情報をメモリに保持します-そして、NAT を実行するときに遅すぎることはありません (何百ものコンピューターを持つ企業は、インターネットに NAT 接続されることがありますが、ほとんどの場合、速度の低下はほとんど目立ちません)。1 秒間に最大 1000 のトランザクションが必要だとおっしゃいましたが、クライアントは何人になるのでしょうか? これは主に、マッピングのバックアップに必要なメモリのサイズを定義するためです。クライアントが多すぎない場合は、メモリ内のソートされたテーブルを使用してマッピングを保持できます。その場合、速度が最小の問題になります (テーブルが大きくなり、サーバーのメモリ不足がより大きな問題になります)。

私には少し不明確なのは、あなたがかつて言ったことです

幸いなことに、クライアントは、これらの ID を持つものの約 20 程度のインスタンス (パッケージと呼びましょう) しか持っておらず、ローカルの兄弟間でそれらを一意にする必要があるだけです。

しかし、あなたは言う

65535 未満の一部の ID は、有効期限が切れていないため、任意の時点で特定のクライアントで引き続き有効である可能性があります。

2 番目のステートメントでおそらく意味していたのは、クライアントが ID 65536 を要求した場合、ID は 65535 未満であり、これらは (たとえば) 20 まで低くなる可能性があるということです。クライアントが ID を順不同ですよね?つまり、65536 を要求したからといって、値が小さいかもしれませんが、1 ~ 1000 の範囲ではないことは確かです。正しいですか? 実際には 20、90、2005、および 41238 への参照を保持していても、65535 を超えている可能性があります。

個人的には、3 番目のアプローチよりも 2 番目のアプローチが好きです。どのような場合でも衝突を回避する方が簡単で、数値を逆に変換するのは単純で単純な操作だからです。あなたの3番目のアプローチが長期的にはうまくいくとは思えませんが. さて、数値の 2^16 を引いた頻度を格納するバイトがあるかもしれません。ただし、最大数として 117 * 2^16 しか減算できません。数字がそれを超えたらどうしますか?別のアルゴリズムを使用すると、減算は行われませんが、何を行いますか? 分ける?ビットをシフトしますか?その場合、粒度が失われます。つまり、このアルゴリズムはヒットできません可能な数はもうありません(大きなジャンプが発生します)。32 ビットに魔法の変換関数を適用して 16 ビット (+ 1 バイト追加) を作成し、それを元に戻すのがとても簡単だったとしたら、この世界のすべての圧縮方法でそれが使用されると思います。 32 ビットの数値が何であれ、常に 24 ビット (16 ビット + 1 バイト) に圧縮してください。それは魔法でしょう。32 ビットを 24 ビットにパックすることはできません。また、それを変換するすべてのロジックもパックすることはできません。外部ストレージが必要になるため、2 番目のアプローチに戻ります。これが機能する唯一のアプローチであり、32 ビット数値範囲のすべての数値に対して機能します。

于 2008-09-23T20:26:35.997 に答える
0

65535 よりどれだけ「多い」必要がありますか? IDの上位ビットとして、「バイトフィールド」から数ビットをいつでも追加できます。わずか 2 ビットで 262,143 になり、3 ビットで 524,287 になります。

于 2008-09-23T19:49:28.610 に答える