Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PostgreSQL Built in Sharding

PostgreSQL Built in Sharding

This presentation describes built-in sharding and its challenges, which is built using only PostgreSQL functionality.

nuko_yokohama

July 03, 2023
Tweet

More Decks by nuko_yokohama

Other Decks in Technology

Transcript

  1. PostgreSQL Built-in Sharding
    PostgreSQL Unconferecnce #42 (2023-07-03)

    View full-size slide

  2. 自己紹介
    ● ぬこ@横浜 , @nuko_yokohama
    ● にゃーん
    ● 趣味でポスグレをやってる者だ
    ● ねこなのでシャーディングむずかしいです

    View full-size slide

  3. PostgreSQL シャーディング

    View full-size slide

  4. シャーディングって何?
    ● データの水平分散
    ● 複数のノードにデータを分割して格納
    ● 複数ノード化することで処理分散効果を見込める

    View full-size slide

  5. PostgreSQL におけるシャーディング
    ● Citus
    – PostgreSQL 拡張機能で実装
    ● Azure Cosmos DB for PostgreSQL
    – Citus ベースのマネージドサービス
    ● Built-in Sharding → 今日はこっちを話します

    View full-size slide

  6. PostgreSQL Built-in Sharding
    ● パーティション+ postgres_fdw
    ● PostgreSQL の標準機能「だけ」で使える
    パーティションノード
    パーティション(親)
    外部テーブル(子) 外部テーブル(子) 外部テーブル(子)
    テーブル
    シャードノード シャードノード シャードノード
    テーブル テーブル

    View full-size slide

  7. Built-in Sharding の例
    ● パーティション機能+ postgres_fdw
    パーティションノード
    パーティション(親)
    外部テーブル(子) 外部テーブル(子) 外部テーブル(子)
    テーブル
    シャードノード シャードノード シャードノード
    テーブル テーブル
    CREATE TABLE ...
    PARTITION BY ...
    CREATE TABLE ...
    CREATE SERVER...
    CREATE USER MAPPING...
    CREATE FOREIGN TABLE
    PATITION BY...
    データの実体は
    シャードノードにある

    View full-size slide

  8. Built-in Sharding の課題
    ● パーティションノードへの負荷集中
    ● 冗長化
    ● バックアップ / リカバリ
    ● 2 Phase Commit 未対応

    View full-size slide

  9. Built-in Sharding の課題 (1)
    ● パーティションノードへの負荷集中
    パーティションノード
    パーティション(親)
    外部テーブル(子) 外部テーブル(子) 外部テーブル(子)
    テーブル
    シャードノード シャードノード シャードノード
    テーブル テーブル
    AP AP AP AP
    AP
    ここがリソースネックになると
    シャードへ負荷がかけきれない
    ヒマだ~

    View full-size slide

  10. Built-in Sharding の課題 (1)
    ● パーティーションノードの複数化
    テーブル
    シャードノード シャードノード シャードノード
    テーブル テーブル
    AP AP AP AP
    AP
    パーティションノード
    (詳細略)
    パーティションノード
    (詳細略)
    Load balancer
    パーティションノード
    (詳細略)
    面倒そう・・・

    View full-size slide

  11. Built-in Sharding の課題 (1)
    ● パーティションノードの複数化の問題
    – コスト上昇
    – 設定面倒(自動化の検討)
    – 通信量増加→ NW 帯域にも留意

    View full-size slide

  12. Built-in Sharding の課題 (2)
    ● 冗長化
    – ダウンタイム短縮
    ● Streaming Replication
    ● Pacemaker 等による自動 F/O の仕組み
    – 構築 / 運用コストの増加
    – ねこなので Pacemaker にがてです

    View full-size slide

  13. Built-in Sharding の課題 (2)
    ● シャードの冗長化 (PG-REX 構成)
    パーティションノード
    パーティション(親)
    外部テーブル(子) 外部テーブル(子) 外部テーブル(子)
    テーブル
    シャードノード シャードノード シャードノード
    テーブル テーブル
    テーブル
    シャードノード
    Streaming Raplication
    シャードノード
    テーブル
    シャードノード
    テーブル
    Streaming Raplication Streaming Raplication
    Pacemaker
    Pacemaker
    構築も運用も
    大変そうだ・・・
    PM
    PM
    PM
    PM
    パーティションノード
    (詳細略) Pacemaker Pacemaker
    Streaming
    Raplication

    View full-size slide

  14. Built-in Sharding の課題 (3)
    ● バックアップ
    – 厳密に考え出すと、パーティションノード / 全シャードの
    同一タイミングでのオンラインバックアップが必要
    – PostgreSQL 自体には複数ノードの静止点をとる機能はない
    – グローバル XID のような管理情報が本当は必要なのかな?
    ● リストア時→全ノードの同時リストアが必要?
    ● Azure Cosmos DB for PostgreSQL のバックアップ / リストアってどうやっ
    て実現しているんだろう・・・?

    View full-size slide

  15. Built-in Sharding の課題 (4)
    ● 2 Phase Commit 未対応
    – トランザクション実行中に一部のノードがクラッシュした
    場合、トランザクションとしては Rollback しているにもか
    かわらず一部のシャードは Commit される

    View full-size slide

  16. Built-in Sharding の課題 (4)
    ● 一部ノードのクラッシュ問題 (0)
    node0
    addr
    addr_kanagawa addr_tokyo addr_others
    addr_kanagawa
    node1
    addr_tokyo addr_others
    node2 node3
    パーティションキーは
    pref 列です

    View full-size slide

  17. Built-in Sharding の課題 (4)
    ● 一部ノードのクラッシュ問題 (1)
    $ psql -p 16000 -U postgres testdb -a -f append-insert-pf.sql
    TABLE addr;
    id | pref | area | addr
    -------+----------+------------------+-----------
    20001 | 東京都 | 千代田区 | 大手町 Z-Z
    20002 | 東京都 | 武蔵野市 | 緑町 Y-X
    10001 | 神奈川県 | 横浜市中区 | 寿町 X-XX
    10002 | 神奈川県 | 横須賀市 | 光の丘 X-X
    30001 | 埼玉県 | さいたま市大宮区 | 下町 X-XX
    40001 | 千葉県 | 千葉市中央区 | 中央 X-X
    (6 rows)
    パーティションキーは
    pref です

    View full-size slide

  18. Built-in Sharding の課題 (4)
    ● 一部ノードのクラッシュ問題 (2)
    BEGIN;
    BEGIN
    INSERT INTO addr VALUES (10003, ' 神奈川県 ', ' 町田市 ', ' 中央 C-C');
    INSERT 0 1
    INSERT INTO addr VALUES (20003, ' 東京都 ', ' 港区 ', ' 港南 K-K');
    INSERT 0 1
    INSERT INTO addr VALUES (30003, ' 埼玉県 ', ' 行田市 ', ' 十万石 J-J');
    INSERT 0 1
    SELECT pg_sleep(10);
    pg_sleep
    ----------
    (1 row)
    -- sleep 中に node2 を再起動する
    神奈川県は node1
    東京都は node2
    埼玉県は node3

    View full-size slide

  19. Built-in Sharding の課題 (4)
    ● 一部ノードのクラッシュ問題 (3)
    COMMIT;
    psql:append-insert-pf.sql:9: ERROR: server closed the connection unexpectedly
    This probably means the server terminated abnormally
    before or while processing the request.
    CONTEXT: remote SQL command: COMMIT TRANSACTION
    $ psql -p 16000 -U postgres testdb -c "TABLE addr"
    Null display is "(null)".
    id | pref | area | addr
    -------+----------+------------------+-----------
    20001 | 東京都 | 千代田区 | 大手町 Z-Z
    20002 | 東京都 | 武蔵野市 | 緑町 Y-X
    10001 | 神奈川県 | 横浜市中区 | 寿町 X-XX
    10002 | 神奈川県 | 横須賀市 | 光の丘 X-X
    10003 | 神奈川県 | 町田市 | 中央 C-C
    30001 | 埼玉県 | さいたま市大宮区 | 下町 X-XX
    40001 | 千葉県 | 千葉市中央区 | 中央 X-X
    (7 rows)
    COMMIT 時に、単純に
    シャードノードごとに COMMIT を
    発行するのでこうなる・・・
    トランザクションは
    Rollback しているのに
    神奈川県町田市のデータのみ
    COMMIT されている!

    View full-size slide

  20. Built-in Sharding の課題 (4)
    ● 2 Phase Commit 対応: postgres_fdw_plus
    – 藤井さん作成の拡張機能
    https://github.com/MasaoFujii/postgresql/tree/postgres_fdw_plus/contrib/postgres_fdw
    ↓ 今はこっちが開発リポジトリらしいです
    https://github.com/pgfdwplus/postgres_fdw_plus
    – 2 Phase Commit 対応

    View full-size slide

  21. Built-in Sharding の課題 (4)
    ● 一部ノードのクラッシュ問題の対応例 (1)
    $ psql -p 16000 -U postgres testdb -a -f append-insert-pf.sql
    TABLE addr;
    id | pref | area | addr
    -------+----------+------------------+-----------
    20001 | 東京都 | 千代田区 | 大手町 Z-Z
    20002 | 東京都 | 武蔵野市 | 緑町 Y-X
    10001 | 神奈川県 | 横浜市中区 | 寿町 X-XX
    10002 | 神奈川県 | 横須賀市 | 光の丘 X-X
    30001 | 埼玉県 | さいたま市大宮区 | 下町 X-XX
    40001 | 千葉県 | 千葉市中央区 | 中央 X-X
    (6 rows)
    PostgreSQL 16 beta1 環境で
    検証しています。
    各ノードの
    max_prepared_transactions を
    1 以上にするのも忘れずに

    View full-size slide

  22. Built-in Sharding の課題 (4)
    ● 一部ノードのクラッシュ問題の対応例 (2)
    $ psql -p 16000 -U postgres testdb -a -f append-insert.sql
    LOAD 'postgres_fdw_plus';
    LOAD
    SET postgres_fdw.two_phase_commit = on;
    SET
    TABLE addr;
    id | pref | area | addr
    -------+----------+------------------+-----------
    20001 | 東京都 | 千代田区 | 大手町 Z-Z
    20002 | 東京都 | 武蔵野市 | 緑町 Y-X
    10001 | 神奈川県 | 横浜市中区 | 寿町 X-XX
    10002 | 神奈川県 | 横須賀市 | 光の丘 X-X
    30001 | 埼玉県 | さいたま市大宮区 | 下町 X-XX
    40001 | 千葉県 | 千葉市中央区 | 中央 X-X
    (6 rows)
    postgres_fdw.two_phase_commit を
    on にしないと postgres_fdw と
    同じ動作になります。

    View full-size slide

  23. Built-in Sharding の課題 (4)
    ● 一部ノードのクラッシュ問題の対応例 (3)
    BEGIN
    INSERT INTO addr VALUES (10003, ' 神奈川県 ', ' 町田市 ', ' 中央 C-C');
    INSERT 0 1
    INSERT INTO addr VALUES (20003, ' 東京都 ', ' 港区 ', ' 港南 K-K');
    INSERT 0 1
    INSERT INTO addr VALUES (30003, ' 埼玉県 ', ' 行田市 ', ' 十万石 J-J');
    INSERT 0 1
    SELECT pg_sleep(10);
    pg_sleep
    ----------
    (1 row)
    -- sleep 中に node2 を再起動する

    View full-size slide

  24. Built-in Sharding の課題 (4)
    ● 一部ノードのクラッシュ問題の対応例 (4)
    COMMIT;
    psql:append-insert.sql:11: ERROR: server closed the connection unexpectedly
    This probably means the server terminated abnormally
    before or while processing the request.
    CONTEXT: remote SQL command: PREPARE TRANSACTION 'pgfdw_768_16415_29446_null'
    $ psql -p 16000 -U postgres testdb -c "TABLE addr"
    id | pref | area | addr
    -------+----------+------------------+-----------
    20001 | 東京都 | 千代田区 | 大手町 Z-Z
    20002 | 東京都 | 武蔵野市 | 緑町 Y-X
    10001 | 神奈川県 | 横浜市中区 | 寿町 X-XX
    10002 | 神奈川県 | 横須賀市 | 光の丘 X-X
    30001 | 埼玉県 | さいたま市大宮区 | 下町 X-XX
    40001 | 千葉県 | 千葉市中央区 | 中央 X-X
    (6 rows)
    $
    トランザクションは
    Rollback して
    神奈川県町田市の INSERT も
    Rollback されている!

    View full-size slide

  25. Built-in Sharding の課題 (4)
    ● postgres_fdw_plus 利用時の課題
    – PostgreSQL 標準の配布物ではない
    – 利用するためにはビルドが必要
    – 実案件導入の壁がある
    – AWS 等の DBaaS では使えない

    View full-size slide

  26. Built-in Sharding の課題 ( おまけ )
    ● パーティションキーを UPDATE すると奇妙なことに
    $ psql -p 16000 -U postgres testdb -e -f update-partkey.txt
    SELECT * FROM addr;
    id | pref | area | addr
    -------+----------+------------------+-----------
    20001 | 東京都 | 千代田区 | 大手町 Z-Z
    20002 | 東京都 | 武蔵野市 | 緑町 Y-X
    10001 | 神奈川県 | 横浜市中区 | 寿町 X-XX
    10002 | 神奈川県 | 横須賀市 | 光の丘 X-X
    10003 | 神奈川県 | 町田市 | 中央 C-C
    30001 | 埼玉県 | さいたま市大宮区 | 下町 X-XX
    40001 | 千葉県 | 千葉市中央区 | 中央 X-X
    (7 rows)
    UPDATE addr SET pref = ' 東京都 ' WHERE area = ' 町田市 ';
    UPDATE 1
    SELECT * FROM addr WHERE pref = ' 東京都 ';
    id | pref | area | addr
    -------+--------+----------+-----------
    20001 | 東京都 | 千代田区 | 大手町 Z-Z
    20002 | 東京都 | 武蔵野市 | 緑町 Y-X
    (2 rows)
    UPDATE したレコードが消える!?
    UPDATE 結果が
    addr_kanagawa にあるため

    View full-size slide

  27. Built-in Sharding の課題 ( おまけ )
    ● WITH ... (DELETE ... RETURING) INSERT ... なら OK
    $ psql -p 16000 -U postgres testdb -e -f delete-returing-insert.txt
    SELECT * FROM addr;
    id | pref | area | addr
    -------+----------+------------------+-----------
    20001 | 東京都 | 千代田区 | 大手町 Z-Z
    20002 | 東京都 | 武蔵野市 | 緑町 Y-X
    10001 | 神奈川県 | 横浜市中区 | 寿町 X-XX
    10002 | 神奈川県 | 横須賀市 | 光の丘 X-X
    10003 | 神奈川県 | 町田市 | 中央 C-C
    30001 | 埼玉県 | さいたま市大宮区 | 下町 X-XX
    40001 | 千葉県 | 千葉市中央区 | 中央 X-X
    (7 rows)
    WITH del AS (
    DELETE FROM addr WHERE area = ' 町田市 ' RETURNING *
    ) INSERT INTO addr SELECT del.id, ' 東京都 ', del.area, del.addr FROM del;
    INSERT 0 1
    SELECT * FROM addr WHERE pref = ' 東京都 ';
    id | pref | area | addr
    -------+--------+----------+-----------
    20001 | 東京都 | 千代田区 | 大手町 Z-Z
    20002 | 東京都 | 武蔵野市 | 緑町 Y-X
    10003 | 東京都 | 町田市 | 中央 C-C
    (3 rows)
    addr_kanagawa から
    DELETE した結果を
    addr_tokyo に INSERT する

    View full-size slide

  28. まとめ
    ● Built-in シャーディングは可能
    ● 課題
    – 親側の負荷集中、冗長化、バックアップ、 2PC 対応
    ● 運用面が不安→マネージドサービスが安全?
    ● postgres_fdw_plus の標準機能化

    View full-size slide

  29. おしまい

    View full-size slide