1. ビジネスシナリオの紹介
もちろん、州/地域や特定のビジネス関係に応じてデータベースを分割する方法を知っている友人もいます。 さて、ここでの疑問は、データが異なるライブラリの異なるテーブルに保存されるようにするにはどうすればよいかということです。ライブラリで同時実行の圧力を軽減しますか?サブライブラリとテーブル分割のルールをどのように定式化すればよいでしょうか?心配しないでください、もうすぐ来ます 2. 水平データベースとテーブル分割方式1.範囲最初の方法は、次の図に示すように、100万に対して1つのテーブルを使用して、1から1000000、1000001-2000000などのデータ範囲を指定してテーブルを分割することです。 ここに画像の説明を挿入 もちろん、この方法では、特に分散環境ではテーブル ID を維持する必要があります。この分散 ID については、サードパーティのテーブル シャーディング ツールを使用せずに RANGE方式の利点:拡張が簡単で、事前にデータベースとテーブルを構築するだけ RANGE 方式の欠点:ほとんどの読み取りと書き込みは新しいデータにアクセスするため、IO ボトルネックが発生します。これにより、新しいデータベースに過度の負荷がかかるため、推奨されません。 2. ハッシュ係数
このようにして、データをさまざまなデータベースやテーブルに分散することができ、IO ボトルネックの問題を回避できます。 HASHモジュラス方式の利点:データが異なるデータベースやテーブルに均等に分散され、データベースの負荷が軽減される。 HASHモジュール方式のデメリット:拡張が難しく、データを移行するたびにハッシュ値を再計算して異なるデータベースやテーブルに割り当てる必要がある 3. 一貫性のあるハッシュHASH によるモジュロは最も完璧な方法ではありませんが、それは何でしょうか? 一貫性のあるHASHアルゴリズムを使用すると、問題を完全に解決できます。 一般的なHASHアルゴリズム: 一般的なハッシュ アルゴリズムは、任意の長さのバイナリ値を、固定長の短いバイナリ値にマッピングします。この小さなバイナリ値はハッシュ値と呼ばれます。ハッシュ値は、データの一意かつ非常にコンパクトな数値表現です。 分散アプリケーションにおける通常の 一貫性のあるハッシュ アルゴリズム:一般的に使用される このリングは端から端まで接続されています。データベース サーバー ノードが 3 つあるとします。 さて、ここでノード3に障害が発生したと仮定しましょう。 user3 は node4 に落ちることがわかります。ノードの追加と削除の分析を通じて、一貫性のあるハッシュ アルゴリズムは単調性を維持しながらデータ移行を最小限に抑えることができることがわかります。このようなアルゴリズムは分散クラスターに非常に適しており、大量のデータ移行を回避し、サーバーの負荷を軽減します。 もちろん、まだ解決しなければならない問題が 1 つあります。それはバランスです。図から、サーバー ノードが比較的少ない場合、大量のデータが必然的に 1 つのノードに集中し、別のノードにはほとんどデータが集中しないという問題が発生することがわかります。 このデータスキュー問題を解決するために、コンシステントハッシュアルゴリズムは仮想ノードメカニズムを導入します。このメカニズムは、各サービスノードに対して複数のハッシュを計算し、各計算結果の場所に仮想ノードと呼ばれるノードを配置します。具体的なアプローチとしては、まず各物理ノードに関連付けられている仮想ノードの数を決定し、次に IP またはホスト名の後に数字を追加します。例えば、上記の場合、各サーバーごとに3つの仮想ノードを計算できるため、「 たとえば、user1 は 一貫性のある HASH 方式の利点:仮想ノードにより、データが異なるデータベースやテーブルに均等に分散され、ノードの追加や削除が他のノードのデータに影響を与えないことが保証され、高い可用性と強力な災害耐性が実現します。 コンシステント・モジュラス法のデメリット:まあ、上記2つに比べれば、無いと言ってもいいでしょう。 3. ユニットテストさて、もうナンセンスは終わりにして、次はユニットテストです。3つのノードがあり、各ノードには3つの仮想ノードがあると仮定します。 パッケージ com.hyh.core.test; com.hyh.utils.common.StringUtils をインポートします。 org.junit.Test をインポートします。 java.util.LinkedList をインポートします。 java.util.List をインポートします。 java.util.SortedMap をインポートします。 java.util.TreeMap をインポートします。 /** * 一貫性ハッシュテスト * * @著者 heyuhua * @create 2021/1/31 19:50 */ パブリッククラスConsistentHashTest { //ハッシュリングに追加するサーバーのリスト private static String[] servers = {"192.168.5.1", "192.168.5.2", "192.168.5.3"}; // 実際のノード リスト。サーバーがオンラインになったりオフラインになったりするシナリオ、つまり追加と削除のシナリオがより頻繁に発生することを考慮すると、ここでは LinkedList を使用する方が適切です。 private static List<String> realNodes = new LinkedList<>(); //仮想ノード、キーは仮想ノードのハッシュ値を表し、値は仮想ノードの名前を表します private static SortedMap<Integer, String> virtualNodes = new TreeMap<>(); // 1 つの実際のノードは 3 つの仮想ノードに対応します private static final int VIRTUAL_NODES = 3; /** * 仮想ノードでHASHの一貫性をテストする */ @テスト パブリックボイドtestConsistentHash() { 初期化ノード(); 文字列[] ユーザー = {"user1", "user2", "user3", "user4", "user5", "user6", "user7", "user8", "user9"}; (int i = 0; i < users.length; i++) の場合 System.out.println("[" + users[i] + "]のハッシュ値は" + getHash(users[i]) + "、node[" + getServer(users[i]) + "]" にルーティングされます。 } /** * まず元のサーバーを実ノードリストに追加します */ パブリック void initNodes() { (int i = 0; i < servers.length; i++) の場合 realNodes.add(サーバ[i]); (文字列str:実ノード) { (int i = 0; i < VIRTUAL_NODES; i++) の場合 { 文字列 virtualNodeName = str + "-仮想ノード" + String.valueOf(i); int ハッシュ = getHash(仮想ノード名); System.out.println("仮想ノード [" + virtualNodeName + "] が追加されました。ハッシュ値は " + hash です); 仮想ノードをハッシュに格納します。 } } システム出力のprintln(); } // FNV1_32_HASH アルゴリズムを使用してサーバーのハッシュ値を計算します。ここでは hashCode を書き換える方法は使用されず、最終的な効果は変わりません private static int getHash(String str) { 最終的な int p = 16777619; 整数ハッシュ = (int) 2166136261L; (int i = 0; i < str.length(); i++) の場合 ハッシュ = (ハッシュ^str.charAt(i)) * p; ハッシュ += ハッシュ << 13; ハッシュ ^= ハッシュ >> 7; ハッシュ += ハッシュ << 3; ハッシュ ^= ハッシュ >> 17; ハッシュ += ハッシュ << 5; // 計算値が負の場合、その絶対値を取得します if (hash < 0) ハッシュ = Math.abs(ハッシュ); ハッシュを返します。 } //ルーティング先のノードを取得する private static String getServer(String key) { //キーのハッシュ値を取得します。 int hash = getHash(key); // ハッシュ値より大きいすべてのマップを取得します SortedMap<Integer, String> subMap = virtualNodes.tailMap(hash); 文字列仮想ノード; サブマップが空の場合(){ //キーより大きいハッシュ値がない場合は、最初のノードから開始します。Integer i = virtualNodes.firstKey(); //対応するサーバーを返します。virtualNode = virtualNodes.get(i); } それ以外 { //最初のキーは時計回り方向にノードに最も近いノードです。Integer i = subMap.firstKey(); //対応するサーバーを返します。virtualNode = subMap.get(i); } //virtualNode 仮想ノード名をインターセプトする必要があります if (StringUtils.isNotBlank(virtualNode)) { virtualNode.substring(0, virtualNode.indexOf("-")) を返します。 } null を返します。 } } ここでは、9つのユーザーオブジェクトがハッシュされた後にルーティングされる状況をシミュレートします。結果を見る 要約: 分散マイクロサービス アーキテクチャ環境では、シャーディングに一貫性のある 以下もご興味があるかもしれません:
|
>>: 行間隔が広い場合の解決策(IE では 5 ピクセル多い)
この記事の例では、ネイティブJSカプセル化vueタブ切り替えの具体的なコードを参考までに共有していま...
フレーム:スタイル=”border-style:solid;border-width:5px;bor...
PHP のコンパイル時に -enable-gd-jis-conv オプションを追加することで発生する...
序文システムの高可用性を満たすためには、通常、クラスターを構築する必要があります。ホストがクラッシュ...
HTML ドキュメント内の要素は次々に配置され、ブロックレベル要素の前後に改行が追加されるだけで、合...
Tomcat は Java 言語をベースにした Web サーバー ソフトウェアです。この記事では主に...
目次ネイティブJS GETリクエストの送信方法投稿リクエストの送信方法パラメータ付きのGETリクエス...
目次Tomcat8のインストールと設定方法tomcat ダウンロードTomcat マネージャーを有効...
管理者権限でcmdを実行する slmgr /ipk CB7KF-BWN84-R7R2Y-793K2-...
MySQL を使用して中国語の文字を挿入すると、多くの友人から次のエラーが報告されます。 これは、文...
RHEL/CentOS シリーズの Linux オペレーティング システムには MySQL ソース自...
背景ディープラーニング モデルの推論には、特定のデバイスが使用されます。マシンは、モデルの読み込み、...
新しいserver.jsを作成する糸初期化 -y 糸を追加エクスプレスノードモン -D var ex...
目次1. コンポーネントの登録1.1 グローバル登録1.2 グローバルコンポーネントの登録プロセス1...
目次1. インデックスとは何ですか? 2. インデックスはなぜ必要なのでしょうか? 3. インデック...