インフラブログ

とあるWEBサイトのインフラを構築運用するメモ

HAProxyでMySQL slaveの通信を分散する

初めにだらだらと概要を書く

MySQLの負荷分散として更新系のmaster、参照系のslaveでインスタンスを複数台用意することにします。slaveについては負荷に応じて台数を増減する予定です。

アプリからみてslaveサーバが何台あるか意識しなくてもいいようにHAProxyを用意します。 HAProxyがアプリとMySQLサーバの通信の中継役を行ってくれるので、アプリからは常にHAProxyだけ見えていればOKとなります。 HAProxy側で複数のslaveサーバに接続を分散してくれます。もしslaveサーバのどれかがダウンしてるときはそのサーバには接続を振らないようにもしてくれます。

また、「負荷に備えてslaveを増設したけど暖気が終わるまで接続を振りたくない」という場合に、設定を一時的に変更することでそのサーバに接続を振らないようにもできます。 接続数の重みづけの調整もできるので、じわじわと接続数を増やしていくということもできそうです。

当初MySQLだけでなくRedisの中継も行おうと考えていたのですが、RedisはElastiCache側でうまく分散してくれるようなので、MySQLのSlaveだけに使用することにします。

インストールと設定

インストールはyumですんなり入ります。 またコマンド経由でhaproxyを制御できるようにhaproxyctlを入れます。 こちらはgemでして、$gem install haproxyctl ; rbenv rehashでインストールします。

設定内容は以下の感じです /etc/haproxy.cfg

global
  maxconn 4096
  user haproxy
  group haproxy
  daemon
        stats socket /tmp/haproxy level admin
        quiet
        nbproc 1
        log 127.0.0.1 local0 info

defaults
  log global
  mode  tcp
  retries 3
  option redispatch
        option tcplog
        option dontlognull
  maxconn 4096
        timeout connect 10s
        timeout client  10s
        timeout server  10s
        grace 1000

listen mysql-slave
  bind    :3307
  mode    tcp
  balance roundrobin
  option  mysql-check user haproxy
  server  slave1 staging-slave-db-1.example.internal:3306 weight 50 check port 3306 inter 5s rise 2 fall 2
  server  slave2 staging-slave-db-2.example.internal:3306 weight 50 check port 3306 inter 5s rise 2 fall 2
  server  slave3 staging-slave-db-3.example.internal:3306 weight 50 check port 3306 inter 5s rise 2 fall 2
  server  slave4 staging-slave-db-4.example.internal:3306 weight 50 check port 3306 inter 5s rise 2 fall 2
  server  master1 staging-master-db-1.example.internal:3306 check port 3306 inter 5s rise 2 fall 2 backup

MySQLのヘルスチェック

option mysql-check user haproxyという設定で、HAProxyがhaproxyユーザを使ってMySQLサーバに接続を試みてヘルスチェックを行います。 MySQLサーバ側で、haproxyユーザを作っておく必要があります。

grant usage on *.* to 'haproxy'@'%';
flush privileges;

運用中にやりそうな事

例えば、staging-slave-1を何らかの理由で使用したくないという場合は、sudo haproxyctl disable server mysql-slave/slave1で使用されなくなります。 復活させたい場合はsudo haproxyctl enable server mysql-slave/slave1です。

slaveを立ち上げたばかりなので少ない接続数から慣らしていきたいという場合は、他のslaveの重み(weight)より低い数値に変更します。 コマンドとしてはこんな感じです。 sudo haproxyctl set weight mysql-slave/slave1 1 weightの数値は0~256のようで、数が大きいほど接続数も多くなります。

なお、stats socket /tmp/haproxy level adminとしておかないとsetコマンドはpermission deniedで拒否されます。