Miscellaneous notes

主に技術的な雑記的な

「Amazon RDS」vs「オレオレRDS的な何か」(序章)

こんばんは。最近、MySQLじゃなくPostgreSQLを触っていますが、心はいつもMySQL派な @marcy_terui です。

この記事は MySQL Casual Advent Calendar 2014 の15日目の記事です。

ちょっと16日目にかかってしまったので、怒られやしないかとgkbrしてま(ry

MySQL Casual Advent Calendar 2014 - Qiita

Amazon RDS」vs「オレオレRDS的な何か」 #とは

ベンチマーク対決とかじゃありません。

日頃お世話になっている便利なRDSさんですが、そんな便利さに甘んじて…
「RDS以外でまともにMySQLを運用できない」
なんてことにならぬよう、
「俺のRDS」が「Amazon RDS」にどこまで迫れるか
的な意味での対決になります。

また、その無駄な車輪の再発明を通して、改めてMySQL及び、RDS for MySQLを知る機会になれば良いかなと。

何やるの?

まず、RDSといえばフルマネージドでメンテナンスフリー。
自分で完全なメンテナンスフリーはさすがに無理としても、出来る限り構築と運用は自動化かつ簡略化されている必要があります。
なので、基本的にはChefでやっていこうと思います。

とはいえ、RDSの機能はたくさんあるので、一度に全部はちょっと無理です。

  • Multi-AZ (Hot standby)
  • Read replica
  • 自動バックアップ・自動メンテナンス
  • PITR

などなど、メジャーな機能がいっぱいありますが、

ここは、あえてカジュアルに?「メモリ搭載量に合わせた自動チューニング」からやってみたいと思います。

メモリ搭載量に合わせた自動チューニング #とは

RDSには、Paramater Groupと呼ばれる通常はmy.cnf内でやるような設定を行うための機能があります。
このParamater Groupには、いくつかのその中でのみ使える特別な文字列が存在します。

中でも、使用しているインスタンスタイプの搭載メモリ量を表すDBInstanceClassMemoryを使用することで、
スケールアップ(ダウン)を行ってメモリ搭載量が変化しても、
それに合わせた設定値を自動的に適用させることができます。

ちなみに、デフォルトの設定ではinnodb_buffer_pool_size{DBInstanceClassMemory*3/4}となっており、
これはつまり、搭載メモリの3/4がinnodb_buffer_pool_sizeの値となることになります。
あと、max_connectionsでも使っていたりします。

やってみた

前提
  • OSはCentOS6系
MySQLバージョン等
  • oreno_rds::defaultを流すとOracle公式のMySQL5.6のyumリポジトリからインストールします。
    2014-12-15現在のバージョン:5.6.22
設定の書き方

こんな感じで書けます。
各値はRDSのMySQL5.6向けのデフォルト値からとりあえず持ってきました。

oreno_rds_cnf "sample" do
  params({
    'default_storage_engine'     => "InnoDB",
    'binlog_cache_size'          => 32768,
    'binlog_format'              => "MIXED",
    'innodb_file_per_table'      => 1,
    'innodb_flush_method'        => "O_DIRECT",
    'innodb_log_buffer_size'     => 8388608,
    'innodb_log_file_size'       => 134217728,
    'key_buffer_size'            => 16777216,
    'local_infile'               => 1,
    'log_output'                 => "TABLE",
    'log_slave_updates'          => 1,
    'master-info-repository'     => "TABLE",
    'max_binlog_size'            => 134217728,
    'performance_schema'         => 0,
    'read_buffer_size'           => 262144,
    'read_rnd_buffer_size'       => 524288,
    'relay_log_info_repository'  => "TABLE",
    'relay_log_recovery'         => 1,
    'skip-slave-start'           => 1,
    'sync_binlog'                => 1,
    'table_open_cache_instances' => 16,
    'thread_stack'               => 262144,
    'character_set_server'       => "utf8mb4"
  })
end

oreno_rds_autocnf "sample" do
  apply_immediately true
  params({
    'innodb_buffer_pool_size' => 3.0 / 4.0,
    'max_connections' => 1.0 / 12582880.0
  })
end

また、設定を即反映するためにmysqldを即時再起動するかどうか選ぶapply_immediatelyオプションも付けました。
即反映しない場合に時間指定で後でメンテナンスするのは…考え中ですw

内部的には、Ohaiからメモリ搭載量を取ってきて、与えられた値で算出する感じです。

ちなみに、メモリ1GBのサーバで実行するとこんな感じになります。

$ mysql -uroot -e"show variables like 'innodb_buffer_pool_size'"
+-------------------------+-----------+
| Variable_name           | Value     |
+-------------------------+-----------+
| innodb_buffer_pool_size | 783286272 |
+-------------------------+-----------+
$ mysql -uroot -e"show variables like 'max_connections'"
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 83    |
+-----------------+-------+

厳密な1024 * 1024 * 1024 * 指定値の値とは若干ずれてますが、VMから見えるメモリ量とは合っていますので、バグではないです。

これを、Chef Serverに入れて繋がせるなり、S3から落とさせるなり、まあローカルに置きっぱなしにするなりして、起動時に実行させるようにすればスケールアップ(ダウン)時に自動的に設定値が調整されます。

最後に

ソースコードはコチラになります。

marcy-cookbooks/oreno_rds · GitHub

開発は今後も続けていきます。

完成版については、

MySQL Casual in Sapporo

@RKajiyama さんと札幌MySQL勉強会の方と来春くらいまでにやりたいと思って動き出そうとしているので、そこで発表できればと思います。

明日(というか今日)はnippondanjiさんです。これは期待ですね!

MySQL Casual Advent Calendar 2014 - Qiita