web-dev-qa-db-ja.com

PgPoolクエリラグのトラブルシューティング

私はかなり長い間PGpool-IIを使用していますが、一貫して複製できる断続的なラグ(実行に約20秒かかる遅いリクエスト)に気づきました。ここで説明する前に、基盤となるアーキテクチャについて簡単に説明します。

  • ストリーミングレプリケーションを使用する2つの異なるデータベース(1つのマスター、2つのレプリカ)
  • それぞれがそれぞれのpgpoolサーバーと対話します
  • 5つのサーバー間でバランスの取れた2つのクライアントアプリケーション
  • Pgpoolロードバランスモードがオンになっている

接続をマスターサーバーに直接ポイントすることで、遅いクエリを除外することができました。その後、別のクライアントアプリケーションからpgpoolに繰り返しクエリを実行した場合にのみ、ラグを一貫して複製できます。ラグは通常、約2回目の反復で発生します。 connection_cache=offを回すと、ラグの頻度が少なくなり、それほど悪くはありませんが、それでも発生することに気付きました。 pgpoolロギングをオンにして問題を解決しようとしましたが、pgpool.logを尾行した後、何を探すべきかわからないほど多くの情報があり、特に文字列grepERRORを使用しても、ラグが発生している間は何も得られません。

構成は次のとおりです。

listen_addresses = '*'
port = 5432
socket_dir = '/var/run/postgresql/'
listen_backlog_multiplier = 2
pcp_listen_addresses = '*'
pcp_port = 9898
pcp_socket_dir = '/var/run/postgresql/'
backend_hostname0 = 'database3-master'
backend_port0 = 5432
backend_weight0 = 1
backend_data_directory0 = '/var/lib/pgsql/data'
backend_flag0 = 'DISALLOW_TO_FAILOVER'
backend_hostname1 = 'database3-replica'
backend_port1 = 5432
backend_weight1 = 1
backend_data_directory1 = '/var/lib/pgsql/data'
backend_flag1 = 'DISALLOW_TO_FAILOVER'
backend_hostname2 = 'database3-replica2'
backend_port2 = 5432
backend_weight2 = 1
backend_data_directory2 = '/var/lib/pgsql/data'
backend_flag2 = 'DISALLOW_TO_FAILOVER'
enable_pool_hba = on
pool_passwd = 'pool_passwd'
authentication_timeout = 60
ssl = off
num_init_children = 32
max_pool = 4
child_life_time = 300
child_max_connections = 0
connection_life_time = 60
client_idle_limit = 0
log_destination = 'stderr'
log_connections = on
log_hostname = off
log_statement = off
log_per_node_statement = off
log_standby_delay = 'none'
syslog_facility = 'LOCAL0'
syslog_ident = 'pgpool'
debug_level = 1
pid_file_name = '/var/run/pgpool/pgpool.pid'
logdir = '/var/log/pgpool/'
connection_cache = off
replication_mode = off
replicate_select = off
insert_lock = on
replication_stop_on_mismatch = off
failover_if_affected_tuples_mismatch = off
load_balance_mode = on
ignore_leading_white_space = on
black_function_list = 'nextval,setval,nextval,setval'
allow_sql_comments = off
master_slave_mode = on
master_slave_sub_mode = 'stream'
sr_check_period = 0
sr_check_user = 'pgpool'
sr_check_password = 'password'
delay_threshold = 0
follow_master_command = '/bin/echo %M > /tmp/postgres_master'
health_check_period = 30
health_check_timeout = 20
health_check_user = 'pg_produser'
health_check_password = '9password'
health_check_max_retries = 0
health_check_retry_delay = 1
connect_timeout = 10000
failover_command = '/etc/pgpool-II/failover.sh %d %H %P /tmp/postgresql.trigger.failover startup-pgpool4'
fail_over_on_backend_error = on
search_primary_node_timeout = 10
recovery_user = 'pgpool'
recovery_password = 'password'
recovery_timeout = 90
client_idle_limit_in_recovery = 0
use_watchdog = on
wd_hostname = 'pgpool3'
wd_port = 9000
wd_authkey = ''
wd_escalation_command = '/bin/bash /etc/pgpool-II/pgpool-failover.sh'
wd_lifecheck_method = 'heartbeat'
wd_interval = 10
wd_heartbeat_port = 9694
heartbeat_destination0 = 'pgpool4'
heartbeat_destination_port0 = 9694
other_pgpool_hostname0 = 'pgpool4'
other_pgpool_port0 = 5432
other_wd_port0 = 9000
relcache_expire = 0
relcache_size = 256
check_temp_table = on
check_unlogged_table = on
memory_cache_enabled = off

私は別の解決策を真剣に検討してきましたが、あまり見つかりませんでした。理想的には、マスターとスレーブにそれぞれ読み取り/書き込み要求を分割するミドルウェアが必要です。 HAPROXYはクエリを解析しないため、これを行う機能はありません。

アプリケーションレベルで、読み取り/書き込みクエリを分割するための理想的なソリューションはありますか? UPDATE/INSERTを使用したクエリはすべてマスターサーバーに送信されると思いますが、何かが足りないように感じます。

要約すると:

  1. Pgpoolラグをデバッグする効率的な方法はありますか?また、何を探す必要がありますか?
  2. そうでない場合、読み取り/書き込みクエリをレプリカ/マスターにそれぞれ分割するためのpgpool以外の理想的なソリューションはありますか?
  3. そうでない場合、高水準言語にとらわれない説明でアプリケーションレベルで読み取り/書き込みクエリを分割する最も信頼できる方法は何ですか?
1
Joseph Persie

私は自分の質問の最初の答えを部分的に理解したようで、ラグタイムを完全に短縮する解決策も見つけましたが、それは将来問題を引き起こす可能性があります。

まず、意味のあるデバッグを解読する方法を教えてください。

  • /bin/sh -c /usr/bin/pgpool -f /etc/pgpool-II/pgpool.conf -d -nデバッグ用に-dパラメーターを渡します。

  • pgpool confを編集して、以下を表示します。

    log_connections = on
    log_hostname = on
    log_statement = on
    log_per_node_statement = on
    
  • pgpoolを再起動し、tcpdumpを実行して、特定の着信クライアント接続をgrepします。

    tcpdump -i eth1 | grep '[clientname] * > [pgpoolhosname]'

  • 別のウィンドウで、LOGおよびその他の有用な情報のpgpoolログをgrepします。

    tail -f /var/log/pgpool/pgpool.log | grep "LOG\|error\|anythingelseuseful"

TCP接続が確立されていたが、pgpoolは数秒後まで何も応答しなかったと判断できました。これにより、アイドル状態の接続が新しい要求を受け入れることに問題があったと思われます。 。

Pgpoolでは、アイドル接続の数は次のように指定されます。

num_init_children = 20
                               # Number of pools
                               # (change requires restart)
max_pool = 4
                               # Number of connections per pool
                               # (change requires restart)

num_init_childrenを100に、max_poolを2に変更しただけです。

ただし、サーバー上で一度に最大200のアイドルプロセスが実行されているため、これにより、将来的にさまざまな問題が発生する可能性があります。プール接続の設定をいじると、ラグが解決したようです。これらの変数の詳細については、次を参照してください。

http://www.pgpool.net/mediawiki/index.php/Relationship_between_max_pool,_num_init_children,_and_max_connectionshttp://www.pgpool.net/mediawiki/index.php/Relationship_between_max_pool、 _num_init_children、_and_max_connections

1
Joseph Persie