AWS、「Amazon Aurora PostgreSQL Limitless Database」を正式提供開始
昨年末に開催されたAWSの年次イベント「re:Invent 2023」で、AWSは「Amazon Aurora Limitless Database」を発表しました。このデータベースは、PostgreSQL/MySQLインターフェースとの互換でありながら、シャーディングによる書き込み性能やストレージ上限が大幅に強化されています。長らくプレビュー状態でしたが、東京リージョンを含めPostgreSQL版が正式提供されました。
Amazon Aurora PostgreSQL Limitless Databaseではデータはシャーディングされ、ルーターが実データのメタデータ管理や分散トランザクション、データ集約などを担います。
※ 画像引用元 https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/limitless-architecture.html
従来のAuroraクラスターはクラスターを構成するインスタンスがユーザーにも見えていましたが、Limitless Databaseはインスタンスの代わりにDBシャードグループとしてコンソールとしてもエンドポイントとしても見えるようになっています。
Limitless Databaseの裏では、PostgreSQLネイティブの foreign table や foreign data wrapper といった機能のほか、Aurora専用のストレージ技術 Grover 、動的なリソーススケーリングを実現する Caspian 、分散システムにおける高精度の時刻同期を提供する Amazon Time Sync Service といったAWS独自の技術が活躍しています。
Amazon Aurora Limitless Databaseそのものについては、AWSJ 星野さんによるAWS Summit Japan 2024での発表『Amazon Aurora Limitless Database内部アーキテクチャ詳解 〜 スケーラビリティと⾼可⽤性の秘密 〜』がわかりやすいです(GA版と一部仕様が変わっている点にご注意ください)
Limitless Databaseのドキュメントも同時に公開されたため、最低限の動作確認をやってみました
やってみた
AWSコンソールからLimitless Databaseを起動する場合、従来のAurora (PostgreSQL Compatible) クラスターの起動フローに、Limitless Database向けの設定を追加で行うだけです。
複数回起動を試みましたが、起動完了までに1時間以上を要しました。
Limitless Databaseのエンジン選択
AWSコンソールのRDSメニューからStandard create→Aurora (PostgreSQL Compatible)を選択し、「Show only versions that support Aurora Limitless Database」のフィルターを有効にすると、Limitless Databaseエンジン(Aurora PostgreSQL with Limitless Database (Compatible with PostgreSQL 16.4)
) が選択されます。
2024/11/01時点では、バージョンは 16.4 に固定されています
Limitless Database固有の設定
Limitless Databaseエンジンを選択すると、Limitless Database固有の選択項目が現れます
キャパシティ範囲をAurora capacity units (ACU)で下限と上限を指定します。
また、可用性のために、各シャードのフェイルオーバー先のスタンバイ数を0~2の範囲で指定します。スタンバイ機を増やすほど可用性も向上しますが、利用費にも跳ね返ります。
DBシャードグループの確認
Limitless Databaseはインスタンスの代わりに DBシャードグループ としてコンソールとしてもエンドポイントとしても見えるようになっています。
Limitless Databaseを起動すると、2種類のロールが起動します
- クラスターの箱としての Limitless cluster
- Limitless cluster内の DB shard group
※再掲
このDBシャードグループに対応するエンドポイントを DB shard groupロールのデータベースのConfigurationタブから確認できます。
AWS APIからもこのDBシャードグループを確認できます。
$ aws rds describe-db-shard-groups
{
"DBShardGroups": [
{
"DBShardGroupResourceId": "shardgroup-58dd7a78ff2c4fb88b27faf0da2dfac7",
"DBShardGroupIdentifier": "my-first-newsql-group",
"DBClusterIdentifier": "my-first-newsql",
"MaxACU": 32.0,
"MinACU": 16.0,
"ComputeRedundancy": 1,
"Status": "available",
"PubliclyAccessible": false,
"Endpoint": "my-first-newsql-group.shardgrp-xxx.ap-northeast-1.rds.amazonaws.com",
"DBShardGroupArn": "arn:aws:rds:ap-northeast-1:12345:shard-group:shardgroup-58dd7a78ff2c4fb88b27faf0da2dfac7",
"TagList": []
}
]
}
$ aws rds describe-db-shard-groups --db-shard-group-identifier my-first-newsql-group
{
"DBShardGroups": [
{
"DBShardGroupResourceId": "shardgroup-58dd7a78ff2c4fb88b27faf0da2dfac7",
"DBShardGroupIdentifier": "my-first-newsql-group",
"DBClusterIdentifier": "my-first-newsql",
"MaxACU": 32.0,
"MinACU": 16.0,
"ComputeRedundancy": 1,
"Status": "available",
"PubliclyAccessible": false,
"Endpoint": "my-first-newsql-group.shardgrp-xxx.ap-northeast-1.rds.amazonaws.com",
"DBShardGroupArn": "arn:aws:rds:ap-northeast-1:12345:shard-group:shardgroup-58dd7a78ff2c4fb88b27faf0da2dfac7",
"TagList": []
}
]
}
接続
接続時には以下に気をつけてください
- データベース名が
postgres_limitless
Aurora のクラスターのライターエンドポイントに接続してみましょう
$ HOST=my-first-newsql-group.cluster-xxx.ap-northeast-1.rds.amazonaws.com
$ psql -h $HOST -U postgres -d postgres_limitless
Password for user postgres:
psql (16.4 (Ubuntu 16.4-0ubuntu0.24.04.2))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.
postgres_limitless=> select version();
version
-------------------------------------------------------------------------------------------------------------
PostgreSQL 16.4 on aarch64-unknown-linux-gnu, compiled by aarch64-unknown-linux-gnu-gcc (GCC) 9.5.0, 64-bit
(1 row)
postgres_limitless=> select aurora_version();
aurora_version
--------------------
16.4-limitless.103
(1 row)
セッションからは、ルーターエンドポイント(ノード)も確認できます
postgres_limitless=> SELECT router_endpoint FROM aurora_limitless_router_endpoints();
router_endpoint
-------------------------------------------------------------------------------------------------------------
cluster-oqxofvg2yqixyxjmyo7ow2gb2m--node-94826-instance-21709.csjmkalu8lxk.ap-northeast-1.rds.amazonaws.com
cluster-oqxofvg2yqixyxjmyo7ow2gb2m--node-58698-instance-68477.csjmkalu8lxk.ap-northeast-1.rds.amazonaws.com
(2 rows)
データベース名(postgres_limitless
)を指定しない場合、以下の様なエラーが発生します
$ psql -h $HOST -U postgres
Password for user postgres:
psql: error: connection to server at "my-first-newsql-group.cluster-xxx.ap-northeast-1.rds.amazonaws.com" (172.31.12.70), port 5432 failed: FATAL: invalid connection request to non-limitless database "postgres" by user "postgres".
DETAIL: Only connections to limitless databases is allowed.
テーブル作成してみる
Limitless Databaseには以下の3種類のテーブルが存在します
- シャードキーを元にデータをシャーディングするsharded テーブル
- 各シャードにデータを格納するreference テーブル(マスタデータなどを想定)
- どこかのシャードに格納されるstandard テーブル(デフォルト)
Redshiftのdistribution keyと同様に、シャード間通信が発生しないようにうまくテーブル設計することで、スケールしやすくなります。
テーブルタイプの違いは次のブログにまとめています
作成したレコードに対して、(例えば、キーのUPDATEによるリシャードのようにして)シャードキーの変更はできず、レコードの削除&再挿入が必要です。
shardedとreferenceテーブルを作ってみましょう
-- standard table
CREATE TABLE foo(a int primary key);
-- sharded table
SET rds_aurora.limitless_create_table_mode='sharded';
SET rds_aurora.limitless_create_table_shard_key='{"item_id"}';
CREATE TABLE items(item_id int, item text);
-- items table と collocated な sharded table
SET rds_aurora.limitless_create_table_collocate_with='items';
CREATE TABLE item_description(item_id int, item_cat varchar, color_id int);
-- reference table
SET rds_aurora.limitless_create_table_mode='reference';
CREATE TABLE colors(color_id int primary key, color varchar);
テーブル一覧を確認します
postgres_limitless=> \d
List of relations
Schema | Name | Type | Owner
--------+--------------------------+-------------------+-----------------------------------
public | colors | foreign table | postgres
public | foo | foreign table | postgres
public | item_description | partitioned table | postgres
public | item_description_fs00001 | foreign table | rds_aurora_limitless_tables_owner
public | item_description_fs00002 | foreign table | rds_aurora_limitless_tables_owner
public | items | partitioned table | postgres
public | items_fs00001 | foreign table | rds_aurora_limitless_tables_owner
public | items_fs00002 | foreign table | rds_aurora_limitless_tables_owner
(8 rows)
postgres_limitless=> SELECT * FROM rds_aurora.limitless_tables;
table_gid | local_oid | schema_name | table_name | table_status | table_type | distribution_key
-----------+-----------+-------------+------------------+--------------+------------+--------------------------
16002 | 17750 | public | colors | active | reference |
16004 | 17756 | public | foo | active | standard |
16001 | 17744 | public | item_description | active | sharded | HASH (item_id, item_cat)
16000 | 17729 | public | items | active | sharded | HASH (item_id, item_cat)
(4 rows)
items
テーブルと item_description
テーブルはシャードIDが同じため、同じシャードに配置されます(collocated)。collocation_id
を確認します。
postgres_limitless=> SELECT * FROM rds_aurora.limitless_table_collocations ORDER BY collocation_id;
collocation_id | schema_name | table_name
----------------+-------------+------------------
16000 | public | items
16000 | public | item_description
(2 rows)
データを投入し、SELECT結果と実行計画を確認します
postgres_limitless=> select c.* from item_description AS i_d JOIN colors AS c ON i_d.color_id = c.color_id;
color_id | color
----------+-------
1 | blue
(1 row)
postgres_limitless=> explain select c.* from item_description AS i_d JOIN colors AS c ON i_d.color_id = c.color_id;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------
Merge Join (cost=3826.67..4432.39 rows=39926 width=36)
Merge Cond: (c.color_id = i_d.color_id)
-> Sort (cost=754.38..757.79 rows=1365 width=36)
Sort Key: c.color_id
-> Foreign Scan on colors c (cost=100.00..683.30 rows=1365 width=36)
-> Sort (cost=3072.29..3086.92 rows=5850 width=4)
Sort Key: i_d.color_id
-> Append (cost=100.00..2706.25 rows=5850 width=4)
-> Async Foreign Scan on item_description_fs00001 i_d_1 (cost=100.00..1338.50 rows=2925 width=4)
-> Async Foreign Scan on item_description_fs00002 i_d_2 (cost=100.00..1338.50 rows=2925 width=4)
(10 rows)
EXPLAIN
には Limitless Database用の rds_aurora.limitless_explain_options
オプションが存在し、ルーターとシャードレベルでの実行計画を確認できます。Limitless Databaseのルーターはデータシャーディング用のルーティング以外にも、クエリーエンジン的な機能も持ち合わせていることに注意が必要です。
ルーターとシャードを確認
rds_aurora.limitless_subclusters
からルーター・シャード情報を確認できます。
postgres_limitless=> SELECT * FROM rds_aurora.limitless_subclusters order by subcluster_id;
subcluster_id | subcluster_type
---------------+-----------------
2 | router
3 | router
4 | shard
5 | shard
(4 rows)
費用
Limitless Databaseのスペックは、r6g.largeのようなインスタンスタイプではなく、Aurora Serverless v2と同じくAurora Capacity Unit(ACU)を指定します。また、ACUはI/O Optimized型のみ選択可能です。
Limitless DatabaseのACU単価はServerless v2のI/O Optimizedと同じであり、例えば東京リージョンの場合、$0.26/ACU/Hourです。
制約
- ベースとなるPostgreSQLのエンジンバージョンは 16.4 のみです
- PostgreSQLのすべてのSQLに対応しているわけでは有りません。詳細はドキュメントをご確認ください (https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/limitless-reference.html)
- PostgreSQLのすべてのエクステンションに対応しているわけでは有りません。詳細はドキュメントをご確認ください(https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/limitless-reference.DDL-limitations.html#limitless-reference.DDL-limitations.Extensions)
- キャパシティ(ACU)は16から6144の範囲で指定可能です。上限の6144はソフトリミットです
- トランザクションはPostgreSQLのRead CommittedとRead UncommittedとRepeatable Readに対応し、serializableには対応しています。
最後に
Amazon Aurora PostgreSQL Limitless Databaseのがついに正式提供開始しました。
RDBでは解決の難しい書き込み性能がシャーディングで解決されており、水平(シャーディング)・垂直(ACU)にスケールし、PostgreSQLのトランザクションとSQLに対応しています。また、ペタバイト級のデータサイズも扱えます。
Amazon Aurora PostgreSQL Limitless Databaseは分散データベースの難しいところの多くが隠蔽され、RDBのような感覚で単一エンドポイントにSQLを投げるだけで使えるよう提供されており、評価・導入しやすいのではないでしょうか。
AuroraのWriteのスケーラビリティやストレージサイズに課題がある場合、ぜひご検討ください。