データベースの水平セグメンテーションを実装するための2つのアイデア

データベースの水平セグメンテーションを実装するための2つのアイデア

導入

インターネット アプリケーションの普及に伴い、膨大なデータの保存とアクセスがシステム設計におけるボトルネック問題となっています。大規模なインターネット アプリケーションの場合、1 日あたり数十億の PV によってデータベースに非常に高い負荷がかかることは間違いありません。これにより、システムの安定性と拡張性に大きな問題が発生しました。データのセグメンテーションとデータ レイヤーの水平拡張を通じて Web サイトのパフォーマンスを向上させることは、アーキテクチャ開発者にとって好ましい方法となっています。

  • データベースを水平に分割する: これにより、単一のマシンの負荷が軽減され、ダウンタイムによる損失を最小限に抑えることができます。
  • 負荷分散戦略: 単一マシンのアクセス負荷を軽減し、ダウンタイムの可能性を減らすことができます。
  • クラスター ソリューション: データベースのダウンタイムによって発生する単一ポイントのデータベース アクセス不能の問題を解決します。
  • 読み取り/書き込み分離戦略: アプリケーション内のデータ読み取りの速度と同時実行性を最大化します。

なぜデータセグメンテーションを行うのですか?

上記は、データ セグメンテーションとは何かについての簡単な説明です。読者は、なぜデータ セグメンテーションが必要なのか疑問に思うかもしれません。 Oracle のような成熟した安定したデータベースは、大量のデータの保存とクエリをサポートするのに十分でしょうか?なぜデータスライスが必要なのでしょうか?

確かに、Oracle の DB は非常に成熟しており安定していますが、高額な使用料とハイエンドのハードウェア サポートはすべての企業にとって手頃な価格ではありません。年間使用料が数千万元、ミニコンピュータのハードウェアサポートに数千万元かかることを想像してみてください。平均的な企業がこれを支払う余裕があるでしょうか?たとえ余裕があっても、より優れたソリューション、より水平方向のスケーラビリティに優れたより安価なソリューションがあるなら、なぜそれを選ばないのでしょうか?

各マシンがどれだけ適切に構成されていても、物理的な限界があることはわかっています。そのため、アプリケーションが 1 台のマシンの特定の限界に達するか、それをはるかに超えると、他のマシンの助けを求めるか、ハードウェアをアップグレードし続けるしかありません。ただし、一般的な解決策は、負荷を分散するためにマシンを追加して水平に拡張することです。また、ビジネス ロジックが拡大し続けるにつれて、マシンが線形成長を通じて需要を満たすことができるかどうかも考慮する必要があります。シャーディングにより、コンピューティング、ストレージ、I/O を複数のマシンに並列に簡単に分散できるため、単一障害点を回避し、システムの可用性を向上させ、エラーを適切に分離しながら、複数のマシンのさまざまな処理機能を最大限に活用できます。

上記の要素を考慮すると、データのセグメンテーションが必要になります。 無料の MySQL と安価なサーバー、または PC を使用してクラスターを構築し、ミニコンピューター + 大規模な商用 DB の効果を実現し、多くの資本投資を削減して運用コストを削減します。なぜそうしないのでしょうか?

大規模および中規模のプロジェクトでは、データベースを設計する際に、データベースが保持できるデータの最大量を考慮して、通常、データベースまたはデータ テーブルは水平に分割され、単一のデータベースまたは単一のテーブルへの負荷が軽減されます。ここでは、2 つのプロジェクトで一般的に使用されるデータ テーブルのセグメンテーション方法を紹介します。もちろん、これらの方法はすべてプログラム内にありますか? 特定のテーブルにルーティングするには、特定のテクニックを使用します。まず、水平分割の基準となるものを確認する必要があります。当社のシステム (SNS) では、ユーザーの UID はシステムを通じて実行され、一意で自動的に増加します。このフィールドに従ってテーブルを分割するのが最適です。

方法1: MD5ハッシュを使用する

この方法は、UID を md5 で暗号化し、最初の数桁 (ここでは最初の 2 桁) を取得して、異なる UID を異なるユーザー テーブル (user_xx) にハッシュするというものです。

関数 getTable( $uid ){
 $ext = substr(md5($uid),0,2);
 "user_".$ext を返します。
}

このトリックを使用すると、異なる UID を 256 個のユーザー テーブル (user_00、user_01...user_ff) に分散できます。 UID は数値であり増加するため、md5 アルゴリズムに従って、ユーザー データを異なるユーザー テーブルにほぼ均等に分散できます。

しかし、ここで問題があります。システムのユーザー数が増えていくと、1 つのテーブル内のデータ量は必然的に大きくなり、このアルゴリズムに従ってテーブルを拡張することができなくなり、記事の冒頭の問題に戻ってしまいます。

方法2: シフトを使用する

具体的な方法は次のとおりです。

パブリック関数 getTable( $uid ) {
 "user_" を返します。sprintf( "d", ($uid >> 20) );
}

ここで、uid を 20 ビット右にシフトして、最初の 100 万程度のユーザー データを最初のテーブル user_0000 に、次の 100 万のユーザー データを 2 番目のテーブル user_0001 に格納できるようにします。ユーザー数が増えた場合は、ユーザー テーブルを追加するだけで済みます。予約するテーブル サフィックスは 4 桁なので、ここでは user_0000、user_0001...user_9999 という 10,000 個のユーザー テーブルを追加できます。 10,000 個のテーブルと各テーブルに 100 万個のデータがある場合、100 億のユーザー レコードを保存できます。もちろん、ユーザー データがこれより多い場合は問題ありません。拡張可能なテーブルを追加するには、予約済みのテーブル サフィックスを変更するだけです。たとえば、データ項目が 1,000 億あり、各テーブルに 100 万が格納されている場合は、100,000 個のテーブルが必要です。テーブル サフィックスは 6 桁のままにしておくだけで済みます。

上記のアルゴリズムは、より柔軟に記述できます。

/**
 * UID パーティショニング アルゴリズムに基づく* @param int $uid // ユーザー ID
 * @param int $bit //テーブルサフィックスに予約されているビット数* @param int $seed //右にシフトするビット数*/
関数 getTable( $uid , $bit , $seed ){
 "user_" を返します。sprintf( "%0{$bit}d" , ($uid >> $seed) );
}

まとめ

上記の両方の方法では、現在のシステム内のユーザー データの量を可能な限り推定し、データベース内の 1 つのテーブルが処理できる最大負荷を推定する必要があります。

たとえば、2 番目のソリューションでは、システムのユーザーが 100 億人いて、1 つのテーブルに最適なデータ量が 100 万であると見積もった場合、各テーブルに 100 万のデータが含まれるように UID を 20 ずつ移動し、ユーザー テーブルの 4 桁 (user_xxxx) を保持して 10,000 テーブルに拡張する必要があります。

もう 1 つの例は、最初のソリューションです。各テーブルに 100 万のデータがあり、最初の 2 桁が MD5 に従って取得される場合、テーブルは 256 個だけになります。システムの合計データベースは、256 * 100 万です。システムの合計データ量がこれを超える場合は、MD5 を使用して最初の 3 桁、4 桁、またはそれ以上の桁を取得する必要があります。

どちらの方法でも、データを水平に分割して異なるテーブルに格納します。最初の方法と比較すると、2 番目の方法の方がスケーラビリティに優れています。

要約する

以上がこの記事の全内容です。この記事の内容が皆様の勉強や仕事に何らかの参考学習価値をもたらすことを願います。123WORDPRESS.COM をご愛顧いただき、誠にありがとうございます。これについてもっと知りたい場合は、次のリンクをご覧ください。

以下もご興味があるかもしれません:
  • MySQL: MySQL 関数
  • MySQL データベースの型変換のための CAST 関数と CONVERT 関数の説明
  • MySQL 8.0.15 インストール グラフィック チュートリアルとデータベースの基礎
  • SQL SERVER データベースのバックアップ コードの例
  • PostgreSQL データベースのウィンドウ関数の構文と使用法
  • データベースの冗長フィールドを合理的に使用する方法
  • MySQL マスター/スレーブ データベース同期構成と一般的なエラー
  • PHP シングルトン モード データベース接続クラスとページ静的実装メソッド
  • MySQL データベースの大文字と小文字の区別の問題
  • データベース言語分類DDL、DCL、DMLの詳しい説明

<<:  Nginx ロケーション設定(ロケーションのマッチング順序)の詳細な説明

>>:  Node.js管理ツールnvmの詳細なインストール手順

推薦する

CSS3.0 でネオンボタンアニメーション効果を実装するためのサンプルコード

今日は、CSS 3.0 で実装されたネオン ボタン アニメーション効果を紹介します。効果は次のとおり...

HTML に埋め込まれた Flash HTML ウェブページ コードに Flash ファイルを埋め込むソリューション (パート 1)

中国の習慣では、旧暦の1月15日より前に新年を祝います。ここで、庭にいる友人たちに新年の幸せを祈りた...

数百万のデータボリュームに対する MySQL ページングクエリ方法とその最適化の提案

データベース SQL の最適化はよくある問題です。何百万ものデータ ボリュームに対してページング ク...

ウェブフロントエンド開発者が知っておくべき 9 つの実用的な CSS プロパティ

1. 角を丸くする今日の Web デザインは、常に最新の開発テクノロジーに追随しており、HTML5 ...

JavaScriptの原理と方向性

これが何を指しているのかをどのように判断するのでしょうか? ①グローバル環境で呼び出された場合はwi...

JavaScriptカスタムオブジェクトメソッドの概要

目次1. オブジェクトを使用してオブジェクトを作成する2. コンストラクタを使用してオブジェクトを作...

CentOS で RPM を使用して MySQL 5.6 をインストールするチュートリアル

これまでのプロジェクトはすべて Windows システム環境にデプロイされていました。今回は Lin...

background-positionプロパティでのパーセンテージ値の使用法の検討

背景位置が背景画像の表示に与える影響この2日間のプロジェクトでホームページの写真を入れ替えていたとこ...

VirtualBoxにOpenSuseをインストールする方法

仮想マシンはホストマシンにインストールされます。 CPU とメモリはホスト マシンと共有する必要があ...

nginxでgzip圧縮を有効にする手順を完了する

目次序文1. gzip圧縮を設定する2. 詳細設定3. nginxサービスを再起動する要約する序文ウ...

HTMLのmarquee属性でテキストを踊らせる

構文: <marquee> …</marquee>モバイル属性マーキーを使用...

MySQL テーブル作成外部キー エラーの解決方法

データベーステーブルA: テーブル task_desc_tab を作成します ( id INT(11...

Ubuntu 19 以下に Android Studio をインストールするチュートリアル

過去の経験から言うと、タスクを完了した後にメモを取るのは良い習慣です。インストール環境はUbuntu...

WeChatアプレットは固定ヘッダーとリストテーブルコンポーネントを実装します

目次必要:機能ポイントレンダリング実装のアイデア具体的なコード(react\taro3.0)特定のコ...

MySQL 全体または単一のテーブルデータのエクスポート

単一のテーブルをエクスポートするmysqldump -u ユーザー -p db名 テーブル名 >...