古代から皇帝の寿命は短かった。皇帝も負荷分散アルゴリズムを理解していたら...

古代から皇帝の寿命は短かった。皇帝も負荷分散アルゴリズムを理解していたら...

[51CTO.com オリジナル記事] 古代の皇帝はハーレムに3000人の美女を抱えていたことは誰もが知っていますが、皇帝は当然、すべての人を平等に扱う精神を持ち、一人だけを優遇することを望まなかったのです。

[[313028]]

画像はPexelsより

川は三千もあるのに、どうしてその一つだけしか飲めないのか。皇帝は夜寝るときに寒さを恐れ、毎晩一緒に寝てくれる人が必要だったという。それでは、後宮にこんなに多くの側室がいる場合、誰を選び、寝る場所の数をどのように割り当てるべきだろうか。

皇帝がセックスにこだわっていたのも不思議ではありません。早くも『春秋実録』には、「陰病を隠して明るい噂を流せば、六気を防いで心臓病を治せる」と記されています。

九人の側室の下では、九人に一人が皇帝と性交する。八十一人の側室は九夜、二十七人の女性は三夜、九人の側室は一夜、三人の妻は一夜、合計十四夜、そして皇后は一人で一夜、合計十五夜。月の前半は上記のように配置され、月の満ち欠けに応じて、月の後半は16日から皇后、九妾、側室、側室の順に始まります...

さまざまな王朝の皇帝は、側室を寵愛する方法がそれぞれ異なっていました。有名なものとしては、羊の荷車の中で寵愛を待つ、サイコロを振って皇帝と寝る、蝶で皇帝を寵愛する、トランプをめくる、提灯を吊るす、などがあります。

しかし、私の意見では、皇帝が負荷分散アルゴリズムを理解していれば、それほど多くのことをする必要はありません。一連のアルゴリズムで、一生眠っている問題を処理できます。そのため、今日は、よく使用される負荷分散アルゴリズムとコード実装をいくつか紹介します。

まず記事の概要を見てみましょう:

  • ポーリングアルゴリズム
  • 加重ラウンドロビン
  • ランダム化アルゴリズム
  • 重み付きランダムアルゴリズム
  • 送信元アドレスハッシュアルゴリズム
  • 一貫性のあるハッシュアルゴリズム

ポーリングアルゴリズム

歴史の記録によると、乾隆帝は生涯で42人の側室を持っていたが、その中には長江の南方に行った際に大明湖に滞在した夏玉和ら他の者も含まれていない。

[[313029]]

ある時期、皇帝の寵愛する側室が霊妃、献妃、高妃、淳妃であったとします。一般的なポーリング アルゴリズムをどのように選択しますか?

まず、妾セットを次のように定義します。

  1. /**
  2. * *すべての側室コレクション
  3. */
  4. public static final List<String> PRINCESS_LIST = Arrays.asList( "Ling Fei""Xian Fei""Gao Gui Fei""Chun Fei" );

次に、リストから寝室で皇帝に仕えている側室に投票し、変数インデックスを使用して投票順位を記録します。

  1. //ループ位置を記録する
  2. プライベート静的整数インデックス= 0;
  3. パブリック静的voidメイン(String[] args) {
  4. ( int i = 0; i < 10; i++) {
  5. System.out.println(getPrincess() ) ;
  6. }
  7. }
  8. プライベート静的文字列 getPrincess() {
  9. // 配列サイズを超えた場合は、ゼロにリセットする必要があります(構成の変更によってインデックスが範囲外になるのを防ぐために、各取得の前に判断されます)
  10. if (インデックス>= PrincessConfig.PRINCESS_LIST.size ( )) {
  11. インデックス= 0;
  12. }
  13. 文字列プリンセス = PrincessConfig.PRINCESS_LIST.get(インデックス);
  14. インデックス++;
  15. プリンセスリターン;
  16. }

出力結果は投稿されません。このアルゴリズムの特徴は、シンプル、シンプル、シンプルです。しかし、大きな欠点もあります。

皇帝が凌妃をより寵愛し、彼女と寝るチャンスを増やしたいとしたらどうでしょうか? その場合は、次の重み付け投票アルゴリズムを使用する必要があります。

加重ラウンドロビン

加重ラウンドロビンは、各妾に対して主観的に優先値(重み値)を設定し、選択される確率を制御するため、次の構成を定義する必要があります。

  1. /**
  2. * *すべての側室コレクション
  3. */
  4. パブリック静的最終Map<String, Integer > PRINCESS_MAP = new LinkedHashMap<String, Integer >() {
  5. {
  6. put( "リンフェイ" , 5);
  7. put( "仙皇后" , 1);
  8. put( "高貴な側室" , 3);
  9. put( "纯妃" , 2);
  10. }
  11. };

ここでの構成はもはや単純なセットではありません。各妾には対応する重み値があります。投票中にこの値に応じて選択される確率を高めるにはどうすればよいでしょうか。

以下では、3 つの一般的な実装について説明します。

重み付けラウンドロビンの実装

私たちのアイデアは、このマップのキー (妾) を重み値に応じてリストに転送し、このリストをポーリングすることです。重み値が 5 の場合、5 つの同一レコードをリストに追加します。

次に、このリストを走査します。重みの値が高いほど、リストに表示される可能性が高くなり、ポーリングされる可能性が高くなります。

  1. //ループ位置を記録する
  2. プライベート静的整数インデックス= 0;
  3. パブリック静的voidメイン(String[] args) {
  4. ( int i = 0; i < 11; i++) {
  5. System.out.println(getPrincess1() ) ;
  6. }
  7. }
  8. プライベート静的文字列 getPrincess1() {
  9. // マップを走査してリストに追加します
  10. リスト<文字列> princessList = 新しい ArrayList<文字列>();
  11. (文字列プリンセス: PrincessConfig.PRINCESS_MAP.keySet()) {
  12. int重み = PrincessConfig.PRINCESS_MAP.get(princess);
  13. // 重み値に応じてリストに繰り返し入れる
  14. ( int i = 0; i < 重み; i++) {
  15. princessList.add(プリンセス);
  16. }
  17. }
  18. if (インデックス>= princessList.size ()) {
  19. インデックス= 0;
  20. }
  21. 文字列プリンセス = princessList.get(インデックス);
  22. インデックス++;
  23. プリンセスリターン;
  24. }

出力は次のようになります。

加重ラウンドロビン アルゴリズムは比較的単純で、実装も簡単です。しかし、問題もあります。設定した重みの値は 5、1、3、2 です。これを 50、10、30、20 に設定することもできますか?

上記の方法によると、何百もの同じ要素をリストに入れる必要があるのでしょうか? これは明らかに不合理であり、メモリを大量に消費します。

加重ラウンドロビン実装 2

上記のアルゴリズムの問​​題に基づいて、類似の比率アプローチを使用して対処することを検討します。

たとえば、設定した重みの値が 50、10、30、20 の場合、水平軸では 0_____50_60__80__110 と表されます。

投票位置を記録するために、インデックスを使用します。インデックスが 0 から 50 の間であれば、最初の妾が選択されていることを意味します。50 から 60 の間であれば、2 番目の妾が選択されていることを意味します。

具体的なコード実装を見てみましょう。

  1. //ループ位置を記録する
  2. プライベート静的整数インデックス整数 = 0;
  3. パブリック静的voidメイン(String[] args) {
  4. ( int i = 0; i < 11; i++) {
  5. System.out.println(getPrincess2() ) ;
  6. }
  7. }
  8. プライベート静的文字列 getPrincess2() {
  9. //合計重量値を記録
  10. 合計重量 = 0;
  11. (文字列プリンセス: PrincessConfig.PRINCESS_MAP.keySet()) {
  12. int重み = PrincessConfig.PRINCESS_MAP.get(princess);
  13. 総重量 += 重量;
  14. }
  15. // ゼロに戻る
  16. if (インデックス整数 >= 総重量) {
  17. インデックス整数 = 0;
  18. }
  19. intインデックス= indexInteger;
  20. 文字列結果 = null ;
  21. (文字列プリンセス: PrincessConfig.PRINCESS_MAP.keySet()) {
  22. int重み = PrincessConfig.PRINCESS_MAP.get(princess);
  23. // 現在の間隔に収まり、直接戻ります
  24. if (インデックス< 重み ) {
  25. 結果 = プリンセス;
  26. 壊す;
  27. }
  28. // 現在の間隔には入らず、ループを続行します
  29. インデックス=インデックス- 重み;
  30. }
  31. インデックス整数++;
  32. 結果を返します
  33. }

出力は上記の方法とまったく同じです。

この加重ポーリング アルゴリズムは最初のものよりも少し複雑ですが、これら 2 つの実装に共通する問題は、現在の構成によれば、霊妃を 5 回連続でポーリングし、次に仙妃を 1 回、次に高妃を 3 回ポーリングすることになるということです...

5回連続!皇帝が霊妃を愛していたとしても、耐えられないでしょう!コンピューター的には、負荷があまりバランスが取れていません!

加重ポーリングの実装 3 (スムーズ加重ポーリング)

スムーズな重み付けポーリング アルゴリズムは、上記の負荷不均衡の状況を解決するために設計されています。このアルゴリズムの実装は比較的複雑です。

各妾には、重量値 (weight) だけでなく、計算を支援するために変化する動的重量値 (dynamicWeight) もあります。

動的重み値の計算ロジックは次のとおりです。

  • 動的重み値 dynamicWeight の初期値は 0 です。
  • 対象の妾を取得するためにポーリングするたびに、最初に dynamicWeight=dynamicWeight+weight を設定します。
  • 次に、すべての妾の中で、動的重み値 dynamicWeight が最も大きい妾を見つけます。これが、この投票の対象です。
  • 今回ポーリングした対象のdynamicWeightをdynamicWeight-totalWeight(合計重量値)に設定します。

これはあまり明確ではないかもしれないので、次の構成がまだあると仮定して計算してみましょう (構成には側室の名前と対応する重み値のみが含まれます)。

  1. /**
  2. * *すべての側室コレクション
  3. */
  4. パブリック静的最終Map<String, Integer > PRINCESS_MAP = new LinkedHashMap<String, Integer >() {
  5. {
  6. put( "リンフェイ" , 5);
  7. put( "仙皇后" , 1);
  8. put( "高貴な側室" , 3);
  9. put( "纯妃" , 2);
  10. }
  11. };

上記の構成では、合計重量値 totalWeight=5+1+3+2 は 11 になります。

① 上記のアルゴリズムの最初のポイントによれば、ターゲットの最初のポーリングの前は、dynamicWeight は 0 です。

したがって、4人の妾のweightとdynamicWeightの値は次のようになります。

② 上記アルゴリズムの2番目のポイントによれば、最初のポーリングでターゲットが選択された場合、dynamicWeight=dynamicWeight+weightとなります。

変更後、4人の妾のweightとdynamicWeightの値は次のようになります。

③上記アルゴリズムの3番目のポイントに従って、最大のdynamicWeightが5であることがわかるので、最初のポーリングではリン皇妾が選択されます。

④上記アルゴリズムの4番目のポイントに従って、TotalWeightからConcubine LingのdynamicWeightを減算する必要があります。

変更後、4人の妾のweightとdynamicWeightの値は次のようになります。

次に、2 回目のポーリング中に、アルゴリズムの最初のポイントに従って dynamicWeight を設定する必要があります。

最後の 4 つの妾の weight と dynamicWeight の値を次のように設定します。

アルゴリズムはこのように処理を続けます。11 回のポーリング後、すべての妾の dynamicWeight は再び 0 になります...

まだ少し混乱している場合は、コードのみをお見せします。まず、各妾とそれに対応する weight および dynamicWeight 属性を格納するためのエンティティを定義する必要があります。

  1. /**
  2. **重量エンティティ
  3. *
  4. * @著者サリバン
  5. *
  6. */
  7. パブリッククラス PrincessWeight {
  8. プライベートストリングプリンセス;
  9. プライベート整数の重み。
  10. プライベート整数dynamicWeight;
  11. パブリックPrincessWeight(String princess, Integer weight, Integer dynamicWeight) {
  12. 素晴らしい();
  13. this.princess = プリンセス;
  14. this.weight = 重量;
  15. this.dynamicWeight = dynamicWeight;
  16. }
  17. }

次に、オブジェクトを格納するための 2 つのグローバル オブジェクトを定義します。

  1. // 各妾とそれに対応する重みエンティティ
  2. プライベート静的Map<String, PrincessWeight> weightMap = new HashMap<String, PrincessWeight>();
  3. // 合計重量値
  4. プライベート静的int totalWeight = 0;

次にアルゴリズムを実装します。

  1. プライベート静的文字列 getPrincess() {
  2. // 妾とそれに対応する重みエンティティを初期化する
  3. (weightMap.isEmpty())の場合{
  4. //マップに設定を初期化する
  5. (文字列プリンセス: PrincessConfig.PRINCESS_MAP.keySet()) {
  6. // アルゴリズムの最初のポイント: 初期の dynamicWeight は 0 です
  7. weightMap.put(princess, 新しい PrincessWeight(princess, PrincessConfig.PRINCESS_MAP.get(princess), 0));
  8. 合計体重 += PrincessConfig.PRINCESS_MAP.get(princess);
  9. }
  10. }
  11. // アルゴリズムの 2 番目のポイント: set currentWeight = set weight + currentWeight
  12. (PrincessWeight の重量: weightMap.values ()) {
  13. weight.setDynamicWeight(weight.getWeight() + weight.getDynamicWeight());
  14. }
  15. // アルゴリズムの3番目のポイント: 最大のcurrentWeightを見つける
  16. プリンセスの体重 maxPrincessWeight = null ;
  17. (PrincessWeight の重量: weightMap.values ()) {
  18. maxPrincessWeight == null の場合 || weight.getDynamicWeight() > maxPrincessWeight.getDynamicWeight()) {
  19. maxPrincessWeight = 重量;
  20. }
  21. }
  22. // アルゴリズムの 4 番目のポイント: 最大 dynamicWeight = dynamicWeight-totalWeight
  23. maxPrincessWeight.setDynamicWeight(maxPrincessWeight.getDynamicWeight() - 合計重量);
  24. maxPrincessWeight.getPrincess()を返します
  25. }

最終的な出力は次のようになります。

11回の投票後、霊公妃も5回登場しましたが、以前のアルゴリズムのように連続して登場することはないことは明らかです。以前のアルゴリズムの方がはるかにバランスが取れています!!! それでも理解できない場合は、記事の最後にあるGithubアドレスからコードをダウンロードして、自分でデバッグして理解することができます。

ランダム化アルゴリズム

滑らかな重み付けポーリングアルゴリズムは、負荷を非常にうまく処理できます。しかし皇帝は再び言いました、ポーリングアルゴリズムによれば、私は毎晩私と一緒に寝る側室を計算できます。まったく面白くありません。

皇帝に関しては、常に何か新しいものや刺激的なものが好きだということは理解できます。幸いなことに、この問題を解決するためのランダム アルゴリズムがあります。毎晩ランダムに 1 つ選択されるため、皇帝は事前に推測できず、十分な興奮を味わうことができます。

私たちは、妾セットを次のように定義します。

  1. /**
  2. * *すべての側室コレクション
  3. */
  4. public static final List<String> PRINCESS_LIST = Arrays.asList( "Ling Fei""Xian Fei""Gao Gui Fei""Chun Fei" );

次に、ランダム関数を使用してターゲットを選択します。

  1. パブリック静的voidメイン(String[] args) {
  2. ( int i = 0; i < 10; i++) {
  3. System.out.println(getPrincess() ) ;
  4. }
  5. }
  6. /**
  7. * *ランダムに側室を獲得
  8. * @戻る
  9. */
  10. プライベート静的文字列 getPrincess() {
  11. セキュアランダム rd = 新しいセキュアランダム();
  12. intインデックス= rd.nextInt ( PrincessConfig.PRINCESS_LIST.size());
  13. PrincessConfig.PRINCESS_LIST.get(インデックス)を返します
  14. }

出力はランダムなので、ここには掲載しません。ポーリング アルゴリズムを理解していれば、ランダム アルゴリズムも簡単に理解できます。ポーリングでは、各ループの位置を保存するためにグローバル インデックスが使用されますが、ランダムでは、値が毎回ランダムに生成されます。

重み付きランダムアルゴリズム

重み付けランダム実装

重み付きランダム実装 1 の考え方は、上記の重み付きポーリング実装 1 とほぼ同じです。コードを直接示します。

  1. パブリック静的voidメイン(String[] args) {
  2. ( int i = 0; i < 10; i++) {
  3. System.out.println(getPrincess() ) ;
  4. }
  5. }
  6. プライベート静的文字列 getPrincess() {
  7. リスト<文字列> princessList = 新しい ArrayList<文字列>();
  8. (文字列プリンセス: PrincessConfig.PRINCESS_MAP.keySet()) {
  9. int重み = PrincessConfig.PRINCESS_MAP.get(princess);
  10. ( int i = 0; i < 重み; i++) {
  11. princessList.add(プリンセス);
  12. }
  13. }
  14. ランダム rd = new Random();
  15. intインデックス= rd.nextInt( princessList.size ());
  16. princessList.get(インデックス)を返します
  17. }

加重ランダム実装 II

重み付きランダム実装 2 の考え方は、上記の重み付きポーリング実装 2 とほぼ同じなので、コードをそのまま示します。

  1. パブリック静的voidメイン(String[] args) {
  2. ( int i = 0; i < 10; i++) {
  3. System.out.println(getPrincess2() ) ;
  4. }
  5. }
  6. プライベート静的文字列 getPrincess2() {
  7. リスト<文字列> princessList = 新しい ArrayList<文字列>();
  8. 合計重量 = 0;
  9. (文字列プリンセス: PrincessConfig.PRINCESS_MAP.keySet()) {
  10. int重み = PrincessConfig.PRINCESS_MAP.get(princess);
  11. 総重量 += 重量;
  12. ( int i = 0; i < 重み; i++) {
  13. princessList.add(プリンセス);
  14. }
  15. }
  16. ランダム rd = new Random();
  17. intインデックス= rd.nextInt(合計重量);
  18. 文字列結果 = null ;
  19. (文字列プリンセス: PrincessConfig.PRINCESS_MAP.keySet()) {
  20. int重み = PrincessConfig.PRINCESS_MAP.get(princess);
  21. // 現在の間隔に収まり、直接戻ります
  22. if (インデックス< 重み ) {
  23. 結果 = プリンセス;
  24. 壊す;
  25. }
  26. // 現在の間隔に該当せず、ループを継続します
  27. インデックス=インデックス- 重み;
  28. }
  29. 結果を返します
  30. }

送信元アドレスハッシュアルゴリズム

私たちの仕事でよく求められるのは、システムにアクセスする前にログインすることであり、これにはセッションが含まれます。

セッションを共有しない場合、ログイン後のセッション情報は、ログイン インターフェイスを呼び出すサーバー上にのみ存在します。

以前のポーリング アルゴリズムまたはランダム アルゴリズムによれば、同じクライアントからの複数の要求が異なるサーバーに送られ、その結果、一部のインターフェイスにアクセスできなくなります。

したがって、同じクライアントからの複数のリクエストが同じサーバーに届く必要があります。ここでの一般的なアプローチは、ソース アドレスをハッシュすることです。

この時点で、私たちは皇帝に休憩を与え、通常のビジネスシナリオに戻らなければなりません。次のようなサーバー構成があるとします。

  1. /**
  2. * *全サーバーコレクション
  3. */
  4. パブリック静的最終リスト<文字列> SERVER_IP_LIST = Arrays.asList(
  5. 「192.168.1.10」
  6. 「192.168.2.20」
  7. 「192.168.3.30」
  8. "192.168.4.40" );

また、クライアントがアクセスする IP アドレスのセットもシミュレートしました。

  1. /**
  2. * *クライアントIP
  3. */
  4. パブリック静的最終リスト<文字列> CLIENT_IP_LIST = Arrays.asList(
  5. 「113.88.97.173」
  6. 「106.11.154.33」
  7. 「207.46.13.149」
  8. 「42.156.137.120」
  9. 「203.208.60.0」
  10. 「119.39.47.182」
  11. 「171.34.179.4」
  12. 「111.175.58.52」
  13. 「124.235.138.199」
  14. "175.184.166.184" );

送信元アドレス ハッシュ アルゴリズムの考え方は、クライアントの IP をハッシュし、ハッシュ値とサーバーの数を法として、アクセスする必要があるサーバーの IP を取得することです。クライアント IP が変更されない限り、ハッシュ値は固定されます。

実装は次のとおりです。

  1. パブリック静的voidメイン(String[] args) {
  2. (文字列クライアントIP: CLIENT_IP_LIST) {
  3. intインデックス= Math.abs (getHash(clientIp)) % PrincessConfig.SERVER_IP_LIST.size ();
  4. 文字列 serverIp = PrincessConfig.SERVER_IP_LIST.get(インデックス);
  5. System.out.println (clientIp + "要求されたサーバーのIPは" + serverIp);
  6. }
  7. }

最終的な出力は次のようになります。

こうすることで、何度実行しても、同じクライアント IP 要求によって取得されるサーバー アドレスは同じになります。

この実装はシンプルですが、脆弱でもあります。サーバーの数は変わる可能性があるため、今日マシンをオフラインにして、明日マシンを追加することはよくあります。

サーバーの数が変わると、送信元アドレスハッシュのモジュロ値が変わる可能性があり、取得されるサーバー IP も当然変わります。

たとえば、サーバーから 192.168.4.10 のマシンを削除すると、次の出力が表示されます。

出力結果を比較すると、影響はほぼグローバルであることがわかります。では、サーバーの数が変わっても影響を受けるクライアントの数を減らすことができるソリューションはありますか? これには、次の一貫したハッシュ アルゴリズムが必要です。

一貫性のあるハッシュアルゴリズム

重み付けポーリング アルゴリズムの 2 番目の実装では、重み値を水平軸表示に変換することについて説明しました。ここでも同じ考え方を使用できますか?

クライアント IP がハッシュ化された後、それは int32 数値になります。次に、int32 数値を複数のセグメントに分割し、各サーバーが 1 つのセグメントのリクエストを担当するようにします。

わかりやすくするために、上記のように、サーバー 192.168.2.10、192.168.2.20、192.168.2.30、192.168.2.40 をそれぞれ IP1、IP2、IP3、IP4 で表します。

  • クライアント IP のハッシュ値が 0 ~ 536870911 の範囲にある場合、IP2 サーバーによって処理されます。
  • クライアント IP のハッシュ値が 536870911 ~ 1073741822 の範囲にある場合、IP3 サーバーによって処理されます。
  • クライアント IP のハッシュ値が 1073741822 ~ 1610612733 の範囲にある場合、IP4 サーバーによって処理されます。
  • クライアント IP のハッシュ値が 1610612733 より大きい場合、処理のために IP1 サーバーに渡されます。

ただし、より専門的な表現では、以下に示すように、水平軸を曲げてハッシュ リングと呼ばれるリングを形成します。

これはより直感的です。ある日 IP4 サーバーがダウンした場合、元々 IP4 に送信する必要があったすべてのリクエストは、処理のために IP1 サーバーに転送されます。

これは依然として一部のクライアント要求に影響を及ぼしますが、少なくとも影響はローカルのみです (次の図を参照)。

これで十分でしょうか? 次の 2 つの質問について考えてみましょう。

  • ハッシュリング上の各サーバーの位置は手動で均等に分散されますが、容量を頻繁に拡張または縮小する必要がある場合、メンテナンスが難しくなりますか?
  • IP4 がダウンすると、元々 IP4 宛てだったすべてのリクエストが IP1 に転送されます。これにより、IP1 でトラフィックの不均衡が生じますか? 元々 IP4 宛てだったトラフィックを IP1、IP2、IP3 に均等に転送できる、よりバランスの取れたソリューションはありますか?

問題 1 の解決策は、ノードの位置を手動で割り当てるのではなく、サーバーの IP に基づいてハッシュ値を計算し、ハッシュ値がリング上のどこに該当するかを確認することです。

これに関する問題の 1 つは、各クラスターのサーバー IP が異なるため、計算後のリング上の位置が制御不能になる可能性があることです。

計算後の 4 つのサーバーの位置は次の図のようになります。

明らかに、この状況は非常に不均一であり、データの偏りが発生します。上記の質問 2 の問題は、実際にはダウンタイムによって引き起こされるデータの偏りです。

リングの左上部分は非常に空いています。現在の 4 台のサーバーを使用して、他のルールに従って左上部分にいくつかのノードを生成することはできますか? この方法では、リクエストはより均等に分散されますか?

これはいわゆる仮想ノードです。仮想ノードとは、同じサーバー IP であり、特定のルールに従って複数のハッシュ コードを生成するため、リング上に複数のノードが存在することになります。

次の図に示すように:

ここでは、サーバーごとに 2 つの仮想ノードをシミュレートしていますが、開発中はさらに多くのノードがシミュレートされる予定です。この方法では、IP4 マシンがクラッシュしても、すべてのリクエストが 1 つのサーバーにプッシュされることはありません。

ここまで述べてきましたが、実装は難しくありません。次はコードを配置します (サーバー構成と要求されたクライアント IP はソース アドレス ハッシュ アルゴリズムと一致しているため、対応するコードをここに貼り付けず、アルゴリズム ロジックを直接配置します)。

  1. //仮想ノードの数: 100
  2. プライベート静的最終整数VIRTUAL_NODES = 100;
  3. パブリック静的voidメイン(String[] args) {
  4. // サーバーIPを走査し、対応する仮想ノードを生成する
  5. TreeMap<整数、文字列> nodeMap = 新しい TreeMap<整数、文字列>();
  6. (文字serverIp : PrincessConfig.SERVER_IP_LIST) {
  7. ( int i = 0; i < VIRTUAL_NODES; i++) {
  8. nodeMap.put(getHash(serverIp + "VN" + i), serverIp);
  9. }
  10. }
  11. (文字列クライアントIP: CLIENT_IP_LIST) {
  12. //ここでは TreeMap の特性が利用されています。よくわからない場合は、tailMap メソッドの役割を自分で学習してください。
  13. SortedMap< Integer 、 String> subMap = nodeMap.tailMap(getHash(clientIp));
  14. 整数firstKey = null ;
  15. 試す {
  16. 最初のキー = subMap.firstKey();
  17. } キャッチ (例外 e) {
  18. }
  19. (firstKey == null )の場合{
  20. 最初のキー = nodeMap.firstKey();
  21. }
  22. System.out.println ( "要求されたサーバーのIPは" + nodeMap.get(firstKey)です);
  23. }
  24. }

この時点で、一般的に使用される負荷分散アルゴリズムとコード実装がいくつか紹介されました。まだ不明な点がある場合は、ゲイの出会い系サイトにアクセスしてサンプル コードをダウンロードし、自分でデバッグすることができます。

  1. https://github.com/sujing910206/負荷分散

著者: 蘇静

紹介: 彼は、大規模なインターネット プロジェクトの開発において長年の経験があり、高同時実行性、分散性、マイクロサービス テクノロジーに関する詳細な研究と関連する実践経験を持っています。私は独学で、テクノロジーの研究と共有に熱心に取り組んでいます。私のモットーは、常に学ぶ心を持つことです。

[51CTO オリジナル記事、パートナーサイトに転載する場合は、元の著者とソースを 51CTO.com として明記してください]

<<:  人工知能の次の転換点: グラフニューラルネットワークが急速な爆発の時代を先導する

>>:  AIとMLでドキュメントを自動化する方法

ブログ    
ブログ    
ブログ    

推薦する

AIは古い文化的シンボルを解体し革新することはできない

1950 年代後半から 1960 年代前半にかけて、一群の芸術家と作家がパリの荒廃したホテルに移り住...

チャットボットが消費者と企業に役立つ6つの方法

チャットボットは非常に一般的になったため、消費者はそれを当然のこととして受け止め、オンライン世界のあ...

機械学習は音楽界を征服するのに役立ち、あなたは次のヴィンセント・ファングになるでしょう

私はアークティック・モンキーズが大好きですが、彼らはもう何年も新しいシングルをリリースしていません。...

2022年までのビッグモデルの未来を展望し、周志華、唐潔、楊紅霞といったビッグネームはどう考えているのだろうか?

年末から年始にかけて、ビッグモデルの過去を振り返り、ビッグモデルの未来に期待してみましょう。 28日...

Java ソートアルゴリズムの概要 (VII): クイックソート

クイックソートはバブルソートの改良版です。その基本的な考え方は、ソート パスを通じて、ソートするデー...

10億枚の画像で訓練されたFacebookの新しいAIモデルは、コンピュータービジョンに革命を起こす可能性がある

この記事はLeiphone.comから転載したものです。転載する場合は、Leiphone.com公式...

放射線科医は再び危機に陥っている!海外の主要5機関が共同で最新の「胸部X線」ベンチマークを発表

胸部X線(CXR)検査は、さまざまな病気のスクリーニングや診断に広く使用されている臨床画像診断法です...

図解機械学習: 誰でも理解できるアルゴリズムの原理

機械学習の話題は誰もが話題にするほど普及していますが、それを完全に理解している人はほとんどいません。...

...

AlphaFold2 の原理: 注意メカニズムが畳み込みネットワークに取って代わり、予測精度が 30% 以上向上

[[412540]]この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI...

RPA プロジェクトを社内で開発すべきでない理由

ロボティック・プロセス・オートメーション (RPA) は、今日最も急速に成長しているテクノロジーの ...

製造業における AI 活用事例 10 選

製造企業は、ビジネスのやり方を合理化し、効率を高めるために人工知能に注目しています。一般的な使用例を...

...