虎の穴開発室ブログ

虎の穴ラボ株式会社所属のエンジニアが書く技術ブログです

MENU

PlanetScaleでシャーディングに触れてみよう

こんにちは、虎の穴ラボのT.Mです。
この記事は「虎の穴ラボ 夏のアドベントカレンダー」9日目の記事です。

8日目は片岡さんによる「タイムトラッキングをやってみましょう」が投稿されました。
10日目は磯江さんによる「アジャイルで生活をカイゼンする」が投稿されます。こちらもぜひご覧ください。

はじめに

突然ですが皆さんはデータベース(以下DB)のパフォーマンスを向上させる場合、何を思い浮かべますか?

最初はINDEXやクエリのチューニング、続いて設定周りの見直しでしょうか。
場合によっては正規化をあえて崩し、テーブルの再設計などを行うかもしれません。
またサーバスペックを上げたり、リードレプリカを増やすなどの負荷分散も試すことでしょう。

今回触れるPlanetScaleは、負荷分散の手法の一つであるシャーディングを得意とします。
シャーディングといえば面倒なイメージがありますが、PlanetScaleはその手間を一手に引き受けてくれる優れものです。

仕事には役立たないかもしれない?

今週のテーマは「仕事には役立たないかもしれない技術」なのですが、「シャーディング」は本当に役立たないのでしょうか。
確かに一般的な規模のサービスからするとシャーディングの導入は、メリットがありつつもオーバースペックなのは否めません。
特に、サービス立ち上げ期に導入する施策としては、候補には上がりにくいものかもしれません。

しかしサービスは成長するもので、負荷分散を重視すべきフェーズはいずれ訪れます。
その際に選択肢として挙がるよう記憶の片隅にでも留めていただければ幸いです。

それではチュートリアルに従い簡単なWEBアプリを作っていきましょう。

シャーディングのメリット

まずシャーディングのメリットですが、一般的にはこれらが挙げられます。

  • 複数のサーバに分割されるため、テーブルあたりのレコード数を少なく保てる
  • レコード数が少ないことからINDEXサイズも同様に小さく、検索パフォーマンスが期待できる
  • 取得したいレコードの保存場所が分かれているため、同時接続を分散できる
  • 物理的にデータが分かれていることによりスケールアウトが容易である

ただしシャーディングは「何でも解決できる魔法の道具」ではないことをご理解ください。
複数のシャードを参照する場合、サーバ間のレイテンシが問題になる場合があります。
また独自実装の際はその複雑さもデメリットとして挙げられるでしょう。

PlanetScaleとは

PlanetScaleとは、Vitessを利用し水平スケーリングを実現したMySQL互換のサーバレスDBプラットフォームです。
※ ただしPlanetScaleはオリジナルのVitessではなくForkしたものを利用しているようです
※ Vitessの歴史について興味がある方はこちらをご参照ください

Vitess自体は様々な機能を持っており、それだけでもシャーディングの実装は可能です。
しかしVitessを正しく活用できるエンジニアとなると数は限られます。
その知識や経験といった部分を全て引き受けてくれるのがPlanetScaleです。

PlanetScaleはサービスに登録し、CLIをインストールするだけでMySQLとほぼ同じ感覚で利用できます。
外部キー制約が使えないという制限がありますが、対応方法は提示されていますのでこちらをご確認ください。

登録方法と注意点

登録自体は簡単に行えますので、順を追って見ていきましょう。
登録時のプランは自動的にフリープランとなり費用はかかりません。
必要に応じてクレジットカードを登録し上位プランに移る方式ですので、安心してお試しいただけます。

それではPlanetScaleにアクセスし、Get startedを押下しましょう。
登録画面へ遷移しますので、メールかGitHub連携での登録を行ってください。

登録するとこの画面が表示されます。
Github連携の場合、組織名にアカウント名がセットされます。
後ほど変更することもできますので、今はこのままで構いません。

登録画面

この後は説明が5ページほど続きます。
最後の画面で「DBの新規作成」か「既存のMySQLをインポート」かを聞かれますが、今回は新規で作成します。

作成時に注意するポイントとして、当たり前ではありますが「最寄りのリージョン」を選択しましょう。
以前はus-westが一番近かったようですが、現在はTokyoもちゃんと選択肢にあります。

リージョン選択

Create databaseを押下でDBが作成されました。
この時点ではusernameやpassword等の設定は不要です。
簡単ですね!

CLIのインストール

コンソールから各種操作を行うために、CLIをインストールしましょう。
ドキュメントのCLIの項目またはCLIのリポジトリのREADME.mdを参照してください。

各OS毎のインストール方法が記載されており、記載されている内容を実行するだけで完了します。

macの場合

$ brew install planetscale/tap/pscale
$ brew install mysql-client

完了したらお約束のバージョン表示でインストールされたことを確認します。

$ pscale --version
pscale version 0.107.0 (build date: 2022-06-30T20:25:44Z commit: 3f2626a)

アプリケージョンの準備

ドキュメントに従い、PlanetScaleを利用するアプリを作成します。
ここではRailsを使いますが、お好みの言語/フレームワークをお試しください。
※ rubyやRailsのインストールは割愛します

rubyとRailsの確認

$ ruby -v
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-darwin19]
$ rails -v
Rails 7.0.3

PlanetScaleのログイン
※ 一旦WEBページに飛ばされて、認証後にコンソールに戻ってきます

$ pscale auth login

Confirmation Code: XXXXXXXX

If something goes wrong, copy and paste this URL into your browser: https://auth.planetscale.com/oauth/device?user_code=XXXXXXXX

Successfully logged in.

ブログアプリの作成とディレクトリへ移動

$ rails new blog
$ cd blog

ドキュメントの通りmysql2をGemfileに追加

$ vi Gemfile
# 「gem "mysql2"」を追記し保存

bundle installの実行

$ bundle install

DBの準備

blogという名称でブログ用のDBを作成します。 しかしフリープランは1台までなので怒られてしまいました。
アカウント作成と同時に作成したDBが既に存在するからですね。

$ pscale database create blog
Error: This organization is at its limit of 1 free database.

再度PlanetScaleを訪れます。
最初に作成したDBを選択後、SettingのGeneralに移動すると一番下にDelete databaseがあるので消してしまいましょう。

削除することで通るようになりました。

$ pscale database create blog
Database blog was successfully created.

View this database in the browser: https://app.planetscale.com/xxxxxxxxx/blog

続いてmainブランチ用のパスワードを設定します。
こちらにhogeと打ち込んだ値は実際のusernameやpasswordではありませんのでご安心ください。
どちらも自動的に生成され、下記のような形で返ってきます。

$ pscale password create blog main hoge
Password hoge was successfully created in blog/main.
Please save the values below as they will not be shown again

  NAME   BRANCH   USERNAME       ACCESS HOST URL                     ROLE    ROLE DESCRIPTION               PASSWORD                                               
 ------ -------- -------------- ----------------------------------- ------- ------------------------------ ------------------------------------------------------- 
  hoge   main     XXXXXXXX   XXXXXXXX.us-east-2.psdb.cloud   admin   Can Read, Write & Administer   pscale_pw_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

しかしACCESS HOST URLがus-east-2になってしまいました。
チュートリアルのpscale database createコマンドにリージョン指定がなかったのが原因です。

これでは困りますので、今度はコマンドラインから先ほどのDBを消してみましょう。

$ pscale database delete blog
? Please type blog to confirm: blog
Database blog was successfully deleted.

リージョンを指定して再度DBを作成します。
利用できるリージョンを知るコマンドはこちらになります。

$ pscale region list
  NAME (9)                            SLUG                 ENABLED  
 ----------------------------------- -------------------- --------- 
  AWS us-east-1 (Northern Virginia)   us-east              Yes      
  AWS us-west-2 (Oregon)              us-west              Yes      
  AWS eu-west-1 (Dublin)              eu-west              Yes      
  AWS ap-south-1 (Mumbai)             ap-south             Yes      
  AWS ap-southeast-1 (Singapore)      ap-southeast         Yes      
  AWS ap-northeast-1 (Tokyo)          ap-northeast         Yes      
  AWS eu-central-1 (Frankfurt)        eu-central           Yes      
  AWS ap-southeast-2 (Sydney)         aws-ap-southeast-2   Yes      
  AWS sa-east-1 (Sao Paulo)           aws-sa-east-1        Yes    

DB作成時にリージョンを指定するパラメータは--regionですので、その後にap-northeastと続けます。

$ pscale database create blog --region ap-northeast
Database blog was successfully created.

View this database in the browser: https://app.planetscale.com/xxxxxxxx/blog

パスワードも同様に再度設定します。
どうやらap-northeast-2で正しく作られたようです。

発行された内容は二度と表示されませんので大切に保管してください。
今回はお試しですので、DBを捨てる前提で忘れてしまっても構いません。

$ pscale password create blog main hoge
Password hoge was successfully created in blog/main.
Please save the values below as they will not be shown again

  NAME   BRANCH   USERNAME       ACCESS HOST URL                          ROLE    ROLE DESCRIPTION               PASSWORD                                               
 ------ -------- -------------- ---------------------------------------- ------- ------------------------------ ------------------------------------------------------- 
  hoge   main     XXXXXXXXX   XXXXXXXXX.ap-northeast-2.psdb.cloud   admin   Can Read, Write & Administer   pscale_pw_XXXXXXXXXXXX

上記の内容で、config/database.ymlを編集します。

development:
  <<: *default
  adapter: mysql2
  database: blog
  username: <USERNAME>
  host: <ACCESS HOST URL>
  password: <PASSWORD>
  ssl_mode: :verify_identity
  sslca: "/etc/ssl/cert.pem"

ここまで来れば後一息です。

PlanetScaleへ戻り、作成したblog DBのSettingを押下。
その中にあるAutomatically copy migration dataにチェックを入れましょう。
Migration frameworkは元からRailsが指定されていると思いますが、異なる場合はRailsに変更してください。

Save database settingsを押下して設定完了です。

完成したアプリを動かす

入れ物の準備はできましたが、まだ中身が空です。
チュートリアルを進めてテーブルを作りましょう。

$ rails generate migration CreateUsers

ここまでチュートリアルの通りに進めた場合、下記のエラーが出ると思われます。

/Users/XXXX/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/bootsnap-1.12.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:15:in `require': cannot load such file -- sprockets/railtie (LoadError)

その場合はGemfileのコメントアウトされたsassc-railsをもどし、bundle installを実行してください。

# Use Sass to process CSS
- #gem "sassc-rails"
+ gem "sassc-rails"

これでマイグレーションファイルができました。

$ rails generate migration CreateUsers
      invoke  active_record
      create    db/migrate/20220704174257_create_users.rb

作成されたマイグレーションファイルを今回は下記の内容で書き換えます。
※ チュートリアルは6系でした

class CreateUsers < ActiveRecord::Migration[7.0]
  def change
    create_table :users do |t|
      t.string :name
      t.string :email
      t.timestamps
    end
  end
end

マイグレーションの実行

$ bin/rails db:migrate
== 20220704174257 CreateUsers: migrating ======================================
-- create_table(:users)
   -> 0.0443s
== 20220704174257 CreateUsers: migrated (0.0443s) =============================

CLIでDBに接続し確認するとテーブルが作られています。

$ pscale shell blog main
blog/main> show tables;
+----------------------+
| Tables_in_blog       |
+----------------------+
| ar_internal_metadata |
| schema_migrations    |
| users                |
+----------------------+
blog/main> desc users;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | bigint       | NO   | PRI | NULL    | auto_increment |
| name       | varchar(255) | YES  |     | NULL    |                |
| email      | varchar(255) | YES  |     | NULL    |                |
| created_at | datetime(6)  | NO   |     | NULL    |                |
| updated_at | datetime(6)  | NO   |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+

これでアプリからマイグレーションを実行し、PlanetScaleに向けてDDL文を発行するところまでできました。
チュートリアルはここまでとなります。

まとめ

一通りチュートリアルを試してみましたが、いかがだったでしょうか。
シャーディングと聞くと難しそうなイメージですが、複雑な部分は全てPlanetScaleが受け持ってくれます。
既存MySQLからのデータ移行方法などもドキュメントにありますので、ハードルはかなり下がったのではないでしょうか。

Amazon RDSとの比較」なんて記事もありますので、PlanetScaleのブログを眺めるのも面白いかもしれません。

明日は磯江さんによる「アジャイルで生活をカイゼンする」です。
実生活に即した楽しい内容となっていますのでご期待ください。

P.S.

虎の穴ラボでは、私たちと一緒に新しいオタク向けサービスを作る仲間を募集しています。
詳しい採用情報は以下をご覧ください。
yumenosora.co.jp