こんにちは、hachi8833です。Craig KerstiensのPostgreSQL記事の翻訳をお送りします。
シャーディング(sharding)はデータを複数サーバーに分散させる機能ですが、導入はそれなりに慎重に行う方がよさそうです。
shard n. (陶器・土器などの)破片.
概要
原著者の許諾を得て翻訳・公開いたします。
- 元記事: Hands on Postgres Sharding
- 元記事公開日: 2016/02/28
- 著者: Craig Kerstiens
ハンズオン: PostgreSQLシャーディング(翻訳)
原注: この記事の内容の多くは現在も有効ですが、今ならCitusの方がもっと直接的に有効です。この記事の公開後、pg_shard
は非推奨になっていますが、Citusにはpg_shard
機能のオープンソース版の上位セットがあるほか、クラウドも提供しています。シャーディングについてのより詳しいガイドは、Citusのブログやドキュメントをご覧ください。
私がデータベースのシャーディングの概要について記事を書いたのは2012年のことでした。以来いくつかの質問を受けていましたが、ここ2か月で質問の数が急増しています。そこで考えた末、ささやかながらシャーディングのハンズオンを行ってシャーディングを深掘りしてみようと思いました。このハンズオンでは、スクラッチでメカニズムをこしらえる代わりにpg_shard
を利用することにもっぱら力を注ぎました。
pg_shard(訳注: 現在はCitusが正式です)をご存じない方向けに説明します。これはCitus Dataが提供するオープンソースのPostgreSQL拡張です。Citus Dataといえばpg_shard++などの商用ソフトェアを連想する方も多いと思いますが、もちろん他にも多くの製品があります。pg_shardで機能をわずかに追加することで、データを自動的に分散できるようになります。分散先が他のPostgreSQLテーブルの場合は論理シャーディング、PostgreSQL データベース/インスタンスの場合は物理シャーディングと呼ばれます。これにより、シンプルさを保ちながら単体のPostgreSQLノードを拡大することができます。
前置きはこのぐらいにして、さっそくハンズオンを始めてみましょう。
ビルドとインストール
ここからは、Mac上で動作するPostgreSQL.app(バージョン9.5)を前提としますが、手順の多くは他のPostgreSQLインストールやOS環境にも簡単に応用できます。
PATH=/Applications/Postgres.app/Contents/Versions/latest/bin/:$PATH make
sudo PATH=/Applications/Postgres.app/Contents/Versions/latest/bin/:$PATH make install
cp /Applications/Postgres.app/Contents/Versions/9.5/share/postgresql/postgresql.conf.sample /Applications/Postgres.app/Contents/Versions/9.5/share/postgresql/postgresql.conf.sample
postgresql.confを以下のように修正します。
#shared_preload_libraries = ''
↓
shared_preload_libraries = 'pg_shard'
続いて/Users/craig/Library/Application\ Support/Postgres/var-9.5/pg_worker_list.conf
に以下のファイルを作成します。パスのcraig
は自分のユーザー名に置き換えてください。
# hostname port-number
localhost 5432
localhost 5433
続いてPostgreSQLインスタンスを作成します。
initdb -D /Users/craig/Library/Application\ Support/Postgres/var-9.5-2
新しく作成されたフォルダ内のpostgresql.confの2箇所で以下を変更します。
port = 5432
↓
port = 5433
最後にデータベースを設定して起動します。
createdb instagram
postgres -D /Users/craig/Library/Application\ Support/Postgres/var-9.5-2
設定
これで2つのPostgreSQLインスタンスが動きましたので、pg_shard拡張をオンにし、テーブルをいくつか作って確認しましょう。まず実行中のPostgreSQLインスタンスのうちメインの方に接続します。ここでは最初にInstagramのデータベースを作成していたので、以下のように設定します。
CREATE EXTENSION pg_shard;
CREATE TABLE customer_reviews (customer_id TEXT NOT NULL, review_date DATE, review_rating INTEGER, product_id CHAR(10));
CREATE TABLE
Time: 4.734 ms
SELECT master_create_distributed_table(table_name := 'customer_reviews', partition_column := 'customer_id');
master_create_distributed_table
---------------------------------
(1 row)
SELECT master_create_worker_shards(table_name := 'customer_reviews', shard_count := 16, replication_factor := 2);
master_create_worker_shards
-----------------------------
(1 row)
仕組みの理解と利用法
最初の設定は以上です。これだけで、共有アプリケーションが理論上最大16インスタンスまでスケール可能になりました。リフレッシャーを使いたい場合、物理シャーディングと論理シャーディングで異なる部分がひとつあります。この場合、論理シャーディングを16インスタンスに拡大し、同じインスタンスから2つの物理PostgreSQLインスタンス間でレプリケーションできます。
データを操作して見る前に、中の様子を少し見てみましょう。まだ接続を切っていなければ、\d
を実行して以下を表示します。
List of relations
Schema | Name | Type | Owner
--------+------------------------+-------+-------
public | customer_reviews | table | craig
public | customer_reviews_10000 | table | craig
public | customer_reviews_10001 | table | craig
public | customer_reviews_10002 | table | craig
public | customer_reviews_10003 | table | craig
public | customer_reviews_10004 | table | craig
public | customer_reviews_10005 | table | craig
public | customer_reviews_10006 | table | craig
public | customer_reviews_10007 | table | craig
public | customer_reviews_10008 | table | craig
public | customer_reviews_10009 | table | craig
public | customer_reviews_10010 | table | craig
public | customer_reviews_10011 | table | craig
public | customer_reviews_10012 | table | craig
public | customer_reviews_10013 | table | craig
public | customer_reviews_10014 | table | craig
public | customer_reviews_10015 | table | craig
(17 rows)
customer_reviews
テーブルがたくさん並んでいます。参考までに申し上げると、これらのテーブルは昔ながらの単なるPostgreSQLのテーブルであり、これらについては何もする必要もなければ気にする必要もありません。これらにクエリをかけたり変更もできます。この不思議なcustomer_reviews
は実際にはすべての論理シャーディング(テーブル)や物理シャーディング(複数マシンに分散)にデータを分散しています。
production環境でプライマリDBを実際にはワーカーとしては使っていない場合に合わせ、ローカルのMacで設定する方法もご紹介します。具体的には、プライマリとは別に複数のワーカーを使うのが普通なので、pg_worker_list.conf
でポートを設定します。通常、以下のような構成になります。
続いてINSERT
を実行します。
INSERT INTO customer_reviews (customer_id, review_rating) VALUES ('HN802', 5);
INSERT INTO customer_reviews (customer_id, review_rating) VALUES ('FA2K1', 10);
ご興味のある方は、保存されているデータがどのように表現されるかについて各自調べてみてください。
まとめ
pg_shard
には多くの制限事項がありますので、pg_shard
リポジトリをご覧ください。それでもpg_shard
はそのままで非常に有用であり、さまざまなシャーディング設定が可能です。アプリでのシャーディングを検討してはいるものの未導入であれば、pg_shard
を使えばわずかな手間でアプリをスケールできるようになります。
次回は、いくつかの言語で有用なシャーディング利用法を見てみることにします。
関連記事(PostgreSQL)
- PostgreSQLの機能と便利技トップ10(2016年版)(翻訳)(人気記事)
- Rails開発者のためのPostgreSQLの便利技(翻訳)(人気記事)
- [Rails] RubyistのためのPostgreSQL EXPLAINガイド(翻訳)
- 【ゆるふわDocker部】任意バージョンのPostgreSQLコマンドを実行して外部DBに接続する