Apache ShardingSphere でシャーディングしてみた

この記事は最終更新から2年以上経過しています。内容が古くなっている可能性があります。

Apache ShardingSphere でシャーディングしてみた

IoTや機械学習ブームもあり、データベースのデータ量は年々増えていき、最近ではTB/PBクラスのサイズになることも珍しいことではありません。

MySQLのレプリケーションクラスタでは、書き込みが許可されるのはマスターノードのみであり、高負荷なWrite処理がスケールできないという点が長年の課題としてあります。

このような場合、複数のマスタにデータを水平分割する(シャーディング)ということを思いつくかと思います。

これまでにも、この課題をミドルウェアで解決しようといくつかの製品がリリースされてきました。一例としては以下があります。

  • MySQL Fabric
  • Spider Storage Engine

また、MySQLフォークの製品として、シャーディングをネイティブに実装している製品もいくつかあります。

  • Vitess
  • TiDB

今回は、このシャーディングに焦点を当て、MySQLにも利用可能なミドルウェアである Apache Sharding Sphere を使ってみようと思います。

Apache ShardingSphere(以下ShardingSphere) は、2022/4/16 にApacheでもトップレベルプロジェクトとなっています。

ShardingSphere became an Apache Top-Level Project on April 16, 2020.

目次

MySQLの起動

事前に3ノードのMySQLを起動しました。

ShardingSphereの種類

ShardingSphere は、以下の2パターンのミドルウェアを提供しています。

  • ShardingSphere-JDBC
  • ShardingSphere-Proxy

いずれも基本的な機能としては同様ですが、Java アプリケーションであればShardingSphere-JDBCを利用することが良いと考えられます。
一方で、ShardingSphere-Proxy を使用することで、どのような言語のアプリケーションでもShardingSphereの機能を利用できるというメリットがあります。
オフィシャルの比較表を見ていただくとわかりやすいと思います。

https://shardingsphere.apache.org/document/current/en/concepts/adaptor/

今回は、ShardingSphere-Proxy を使用します。

ShardingSphereドキュメントの注意

https://shardingsphere.apache.org/document/current は最新のバージョンを一部反映していないようです。

各バージョンのブランチのGithubソースに含まれるdocumentディレクトリを参照することで適切な情報が確認できます。

ShardingSphereのインストール

ShardingSphereはJava製のミドルウェアになりますので、JDKのインストールが必要です。

Downloadページ から最新のパッケージをダウンロードします。
執筆時点では、v5.1.1 になります。
※ 程なくしてv5.1.2がリリースされたため、現在のダウンロードリンクは以下になります。
https://dlcdn.apache.org/shardingsphere/5.1.2/apache-shardingsphere-5.1.2-shardingsphere-proxy-bin.tar.gz

インストール作業を進めます。
ユーザ追加と、ディレクトリの配置のみです。
今回のインストール先は /opt/shardingsphere としました。

JDBC Driverの配置

クイックスタートに記載の通り、各データベースへの接続のためにJDBC Driverをlibもしくはext-lib配下に配置する必要があります。

https://shardingsphere.apache.org/document/current/en/quick-start/shardingsphere-proxy-quick-start/

If the backend database is MySQL, please download mysql-connector-java-5.1.47.jar or mysql-connector-java-8.0.11.jar and put it into the %SHARDINGSPHERE_PROXY_HOME%/ext-lib directory.

ext-libを使用する場合、ディレクトリを作成する必要があります。ここでは、lib配下にダウンロードしました。

ShardingSphereの設定

ShardingSphereは起動スクリプト(start.sh)の親階層のconfディレクトリ以下のyamlファイルを読み取ります。

いくつかのサンプルコンフィグが含まれていますが、シャーディングなどは後ほど行うことにし、server.yamlを編集し基本的な設定で起動します。

起動停止を簡単にするためにサービス化し、起動します。

デフォルトでは、3307ポートでリッスンします。

rules[0].!AUTHORITY.users に指定したユーザで接続が可能です。

DistSQLについて

ShardingSphere では、管理操作のために DistSQL という独自のコマンドを使用します。

https://shardingsphere.apache.org/document/current/en/concepts/distsql/

DistSQL is divided into RDL, RQL and RAL.

RDL (Resource & Rule Definition Language) responsible for the definition of resources and rules;
RQL (Resource & Rule Query Language) responsible for the query of resources and rules;
RAL (Resource & Rule Administration Language) responsible for the added-on administrator feature of hint, transaction type switch, sharding execute planning and so on.

ここでは、シャーディングを達成するための基本的なチュートリアルのみをご紹介しますが、どのようなDistSQL構文があるかはマニュアルをご確認ください。

https://shardingsphere.apache.org/document/current/en/user-manual/shardingsphere-proxy/distsql/

シャーディングについて

シャーディングを実現するためには、以下が最低限必要です。

  • スキーマの作成
  • リソース(データベース接続)の登録
  • シャーディングテーブルルールの作成
  • テーブルを作成

リソースは必ずしも複数無くても構いませんが、スケールアウト戦略を考えている場合は複数になるでしょう。

スキーマの作成

ShardingSphereにスキーマを作成します。
ここでCREATE DATABASEによって作成されるのは、MySQLのデータベースとは関係ありません。

データソースの登録

ShardingSphereにデータベース接続情報を登録します。

起動しているmysqldのポートを確認します。

SSL接続は可能ですが、ここでは簡略化のためにSSL接続を必要としないmysql_native_passwordを設定します。

リソースを以下のように登録します。

シャーディングテーブルの作成

まずはドキュメントの例をもとにシャーディングルールとテーブルを作成します。

このルールでは、シャーディングするデータソースを3つ登録し、自動シャーディングルールによって3つのシャードテーブルに分散させるという内容になっています。
order_idのhash_mod(ハッシュ値の剰余)で対象データソースを決定します。

シャーディングアルゴリズムは、以下に記載があります。

https://shardingsphere.apache.org/document/current/en/user-manual/shardingsphere-jdbc/builtin-algorithm/sharding/

CREATE TABLEの結果、データソース側に t_order_<シャードNo> というテーブルが作成されました。

適当なデータをINSERTしてみましょう。

単純な1~10000の数値をキーにした場合、均等に分散されました。

ShardingSphereからクエリするとすべてのレコードを取得できました。

ShardingSphereにおけるプライマリキーの自動採番

MySQLでは、Auto Incrementによる自動増分値をプライマリキー(もしくはユニークキー)のデフォルト値として利用できます。

当然ながらMySQLの機能としては、複数のmysqldにまたがった連続値の採番などはサポートしていませんので、これは利用できません。

ShardingSphereには、一意のキー生成の仕組み(Key generator)があります。

先程の CREATE SHARDING TABLE RULE に含まれる KEY_GENERATE_STRATEGY がそれにあたります。

今度は、プライマリキーに値を指定せずにINSERTしてみましょう。

その前に、自動生成される値を格納できるように、プライマリキーをBIGINTに変更しておきます。

insertを実行しましょう。

18桁のランダムな番号が更新されました。

この例では、KEY_GENERATE_STRATEGYにSNOWFLAKEを選択しています。

SNOWFLAKEは、Twitter社が開発したエポック時間とその他のビットからなる64bitの一意の数値です。
ランダムな番号ではあるものの、常に最上位bitは0で、次の41bitはエポック時間になるため、Auto increment値のようにソートすることが可能です。

KEY_GENERATE_STRATEGYには他にUUID(32桁の重複しないランダム文字列)も選択できます。
アプリケーションから利用しやすいものを選択するとよいでしょう。

ロードバランス

ShardingSphereは、シャーディングの機能を利用せずにL7ロードバランサとしても動作することが可能です。

MySQLとしてあると嬉しいのが、一般的なソース、レプリカからなるレプリケーション環境をターゲットとした読み書き分割ルーティングですが、
ShardingSphereの機能として備わっています。

この状態でテーブルを作成してみましょう。
なお、ShardingSphereによって実行される実際のSQLは、PREVIEW コマンドによって確認することができます。
テーブルの作成(CREATE TABLE)はprimaryへルーティングされることが確認できました。

INSERT や DELETE, UPDATEも同様にprimaryへルーティングされます。

SELECTはreplica1, replica2へルーティングされました。

データベースのHA機能について

残念ながら、ShardingSphereには組み込みのデータベースに適したHA機能はありません。

ただし、RESOURCEにJDBC URLを登録することができ、JDBCの機能で簡単なフェイルオーバを実装することが可能です。

フェイルオーバすることがわかります。

なお、ShardingSphereには DB_DISCOVERY という機能があり、本来それを使用してフェイルオーバすることが可能ですが、現在サポートされているのはMySQL Group Replication環境のみでした。
次期リリース候補である5.1.2のバージョンから、非同期レプリケーションの機能が追加されるようです。

また、HAと言っておきながらではありますが、ShardingSphereは データベースとしてのHA機能を提供していません
例の通り、接続ができないノードからフェイルオーバすることは可能ですが、一般にMySQLレプリケーション環境においては不十分です。

まず、フェイルオーバ先のデータベース(レプリカ)は通常時READ_ONLYとすることが推奨ですがShardingSphereのフェイルオーバプロセスでそれを解除することはできません。
では、運用カバーするとしてREAD_ONLYは有効化しない場合も、非同期レプリケーションではフェイルオーバ時にレプリカが最新であるか担保されません。
一般的なレプリケーションを考慮したHAソフトウェア(Orchestrator, MHA)は、バイナリログがすべて適用されたことを確認した上でフェイルオーバを完了させます。
レプリカでバイナリログの適用中に更新を入れた場合、更新順序がソースデータベースと異なってしまい、結果的に内容の異なるデータセットになり得るためです。

このような事情もあり、ノード間の整合性が強固に保たれるMySQL Group ReplicationはShardingSphereのようにデータベース製品の整合性を考慮しないプロキシ向けと言えるでしょう。
ただし、最低3ノードが必要ですので、1セット3ノードのシャードを今後追加していくことができるか考慮が必要かと思います。

JDBCのフェイルオーバを利用するのであれば、OrchestratorやMHAのようなソフトウェアと一緒に利用するか、マニュアルでデータベース側の確認、開放を行うかということになります。

という訳でGroup Replication環境を追加しようとしましたが、ドキュメントの例のコマンドは動作しませんでした。

ドキュメントと最新リリースのバージョンが合っていない可能性がありますが、現在も活発に開発が続けられていますので今後に期待したいと思います。

まとめ

パーティショニング、シャーディングといった技術は、サービスが成長するにつれていずれ避けられないことになります。

ネイティブに機能を実装しているソフトウェアを利用しない限り、実施するとなった場合、インスタンスごとに分ける、データベースごとに分けるなど、様々なオプションはありますが、どの方法も一長一短あります。

Apache ShardingSphereのようなプロキシを使ったシャーディングは、ソフトウェアの出来がよければ理想的なソリューションになり得ます。

スケールアウトのために今から製品を検討してみてはいかがでしょうか。

スマートスタイルTECHブログについて

スマートスタイルTECHブログでは、日頃MySQLのサポート業務に従事している有資格者で構成された技術サポートチームがMySQLに関する技術情報を発信しています。データベースのお困りごとはお気軽にご相談下さい。

よかったらシェアしてね!
  • URLをコピーしました!
目次