2013年12月6日金曜日

EC2でプロセッサパワーがほしい時に使うインスタンスはcc2.8xlarge

AWS EC2に新しいc3世代のインスタンスタイプが追加されたのですが、値段あたりの処理性能がいまいちわからなかったのでHeavy Reserved Instanceを1年使う計算で比べてみました。比較対象は c1.xlarge, c3.xlarge, c3.2xlarge, c3.4xlarge, c3.8xlarge, cc2.8xlargeです。3年でもあんまり変わらないと思います。リージョンはバージニアです。

というわけで値段あたりのCPUパワーが一番いいのはcc2.8xlargeでした。c3世代はSSD搭載なので、SSDほしい時は選択肢が変わってくると思いますが、単純にCPUだけほしい、という時はcc2.8xlargeが良さそうです。c3世代より2割ぐらい安い計算になりました。

備忘録的な記事で雑なまとめですがこのへんで。

2013年11月29日金曜日

allocatorを変えてMySQLをベンチしてみた

MySQL Performance Blogにtcmalloc/jemallocを使うとパフォーマンスが良くなるという記事があるので、気になって手元の環境でも計測してみました。

環境

CPUIntel Xeon CPU E5-2620 x 2
OSCentOS 6.4 64bit
MySQLMySQL 5.6.14
sysbenchSysbench 0.4.12
jemallocjemalloc 3.4.1
tcmallocgperftools 2.1

MySQLのmax_connectionsは2048に設定しました。innodb_file_formatはBarracudaで、Buffer poolは56GBを確保し、buffer pool instanceは32に設定しました。

測定内容

sysbench の OLTP テストを下記のようなコマンドで走らせました。

for t in 16 32 64 128 256 512 1024; do sysbench --test=oltp --oltp-table-size=1000000 --mysql-user=benchuser --mysql-password=benchuser --db-driver=mysql --num-threads=$t --max-requests=200000 --oltp-read-only run; done
for t in 16 32 64 128 256 512 1024; do sysbench --test=oltp --oltp-table-size=1000000 --mysql-user=benchuser --mysql-password=benchuser --db-driver=mysql --num-threads=$t --max-requests=200000 run; done

jemalloc の nodirty というのは "MALLOC_CONF=lg_dirty_mult:-1" という環境変数をセットしたものです。これは3.2以降性能がベンチマークによっては劣化することがあるというので気になって測りました。

tcmalloc + large page は、my.cnf に large-page を付けてMySQLを起動したものです。read/writeは取り忘れたのでreadのみです。

なお試行回数は1回で、ベンチマークを2回走らせた2回目の値です(平均とか取ってません)。測定のたびにmysqlを再起動し、cleanup/prepareを実施しました。

allocatorの差し替えは/etc/init.d/mysqlにexport LD_PRELOAD=...を記述する方法を取りました。ロードされていることは/proc/{pid}/mapsを見て確認しました。

測定結果

read/writeに関しては、測定のばらつきが大きく、実行するたびに2割程度は差が出る結果になりましたのであまり信頼の高い結果ではありません。jemallocはスレッド数が1024の場合にのみ、glibc mallocより22%程度高速という結果になりました。tcmallocは16-32スレッドの場合は最大2割遅く、64スレッド以上では1割程度高速でした。

readは比較的安定した結果が出ました。jemallocはglibc mallocと比較し5%程度遅くなりました。tcmallocはglibc mallocと同等または高速で、最大3%程度の差が出ました。

tcmallocでlarge-pageを有効にしても有意な差は見られませんでした。これは今回のデータサイズが小さく、TLBサイズが変わってもヒット率が変わらなかった可能性があります。

考察、まとめ

MySQL Performance blogに掲載されていたような、256スレッド以上ではglibcが遅くなるという現象は見られませんでした。また、jemallocがtcmalloc/glibc mallocとくらべて低速であるという結果になりました。これは設定によるのか、ベンチマークの種類によるのかはわかりませんが、必ずしもjemallocやtcmallocに差し替えることによってMySQLの性能が向上するとは言えない結果になりました。ただしtcmallocはglibc mallocより遅いことはなかったので、差し替えることによってデメリットはメモリの消費量が増える以外は生じないので、メモリに余裕があるのであれば検討してもよいかと思いました。

元のblogでは64スレッドを超えると1万transactions/secを超えているのに対し、こちらではたかだか5000スレッドしか出てません。向こうは32スレッドあるのでこちらより性能が良いのですが、それでも少し性能が低い気がします。ですので、何か設定がまずいのか、それともallocatorが実は差し替わっていない可能性も残っています。

transactions/secだけではなく、CPU使用率やレイテンシにも着目するべきですが、それは今後の課題とします。

2013年11月28日木曜日

Fedora最新技術情報&Systemd勉強会に参加してきました

Linux女子部主催のFedora最新技術情報&Systemd勉強会に参加してきました。

Fedora最新技術情報

講師は藤田稜さん

Fedora最新技術情報といいつつRHEL7のお話でした。いくつか気になった点をピックアップします。

xfsがデフォルトになるかも

RHEL7ではxfsをデフォルトファイルシステムにしたいそうですが、まだ安定性やメモリ消費量に難があり、技術的な観点から決定はしていないそうです。

「RHEL 4, 5, 6 の初期出荷でファイルシステムの破損バグを仕込んだ実績があるので、今からxfsに切り替えたら絶対何か踏む」という声も。

iptablesからfirewalldへ

今までファイアウォールはiptablesを使っていましたが、標準でfirewalldを使うように変更します。従来のiptablesとは排他利用になります。戻すことはできますが、基本的にはfirewalld推奨とのこと。設定を読み込み直すときにreloadしてもセッションが切れなくなっているそうです。

またそれに伴いNetworkManagerが必須となるようで、今まで殺していた人はうまく付き合ってくださいとのことでした。

OpenLMI導入

OpenLMIという管理系機能の共通インタフェースがあるそうなんですが、それがRHEL 7.0GAには入るんじゃないかということ。従来例えばファイルシステムだけ取っても fdisk, gparted, lvm, mkfs など様々なコマンドがバラバラにあったものが、整理され統合されるんだとか。

その他

その他は、systemd入りますよ(後述)、Linux Containerのフルサポート、pNFSのクライアントサポート、実はSELinux enforcedでしかQAしてないので、permissive/disabledはテストしていませんというお話などが聞けました。

大きくはやはり管理系の仕組みがsystemd, OpenLMI, firewalld, NetworkManagerというものに置き換わるのが大きな変更点のようです。「カーネルランドは同じだけどユーザーランドは違うOSと言っても良いほどの変更」と言われていました。

Systemd徹底入門

講師は中井悦司さん

今回のお話のスライドはslideshareにアップロードされていて、時間の都合で省略されたところも含めて詳しく解説されています。ここで細かい話を書いても実際スライドのほうが詳しいので、私が疑問に思った点や補足を中心に記述します。

SysV Init から systemdへ

従来は SysV Init が /sbin/init に存在して最初にpid=1として起動していましたが、代わりに/usr/bin/systemdが起動します。今までは単なるシェルスクリプトが/etc/inittabに定義された順に実行されていたので、シリアルにしか実行できず性能も悪かったものが、systemdではそれぞれのタスクを細かくunitという単位に定義して依存関係と前後関係に基づいて並列的に実行し、起動速度を高速化します。

systemdを作ったのはレナートさんで、彼のblogにどうしてsystemdを作ったのかが載っているので、英語ですがぜひ読んでみてくださいとのこと。systemd の大きな目的は4つあって、

  • システム起動時間の短縮
  • システム構成の動的変更に対応
  • プロセス停止処理を標準機能として提供
  • デーモンの実行環境を制御

です。

依存関係と前後関係

SystemdではRequire/WantedByという依存関係と、Before/Afterという前後関係にもとづいてunitの実行順が決定されます。ここで依存関係というのは単に必要だということを記述するだけで、実際にはその中では平行にunitが実行されていきます。そのため、例えばhttpdが起動する前にDNSが起動しておいてほしい、というようなことはすべて前後関係として記述するようです。

アプリケーションサービスなどもsystemd管理下へ

init だとクラッシュした時の再起動がないので、よくアプリケーションサービスなどを supervisord や daemontools を使って別に起動させていた方も多いと思いますが、基本的には systemd がこれらも含めてすべて見るようにするのが理想的ということです。cgroupを使ってプロセスツリー全体のリソースも管理でき、ログ管理機能もあるのでsystemd管理下に置くほうがシステム全体として整合性も取れるような印象です。

また従来はdaemonizeすることが多かったところsystemdではdaemontoolsのようにforegroundで実行するのが基本的なスタイルになるようです。Typeを変えればforkするデーモンにも対応可能です。

便利そうなコマンド

systemctl status (unit名)すると、関連するプロセスの一覧やログの抜粋が表示される。

systemctl list-units すると、現在有効なunitの一覧が表示され、起動に失敗しているものもひと目でわかる。

systemctl list-dependencies (unit名) すると、依存関係がツリー状に表示される。

manページを読もう

作者のレナートさんがドキュメント魔らしく、manページが大変充実しているので、困っても困らなくてもmanページを読めば良いとのことでした。

感想

systemdという巨大な仕様のものを入れることにRed Hat社内でも議論があったそうですが、結局のところ SysV Init がイケてないし置き換えることは必要で、より良いデーモン管理のため導入することにしたそうです。話を聞くと使う分にはちゃんと動きそう、だけども何でもsystemdにやらせるのは「Unixぽくない」と感じます。

浸透のためにはDebianやGentooもsystemdに移る必要があると思うし、もし今後initが複数使われるのであればソフト作者はsystemd用、upstart用というふうにわけて起動スクリプトを用意しなければいけなくなるかもしれません。そういうのは望ましくないので、なんとか一本化してほしいなぁと思いました。

2013年10月26日土曜日

献本御礼: 独習Linux専科 サーバ構築/運用/管理

著者の中井悦司さんから「独習Linux専科」サーバ構築/運用/管理をいただきました。ありがとうございます。僭越ながら書評を書きました。

Linuxを始める人にぴったり

初心者のかたで、これからLinuxを初めて使おうという方には非常におすすめできる本です。インストールの仕方から基本的なコマンドライン操作、システムの概念が解説されています。そして最後にはSamba, PostgreSQL, Ruby on Railsのサーバーを構築する手順まで書かれています。特にWindowsから入ると馴染みのないパッケージ管理(yum/rpm)やシェルの文法などには多くの紙面が割かれています。

最近はインターネットを検索すると多くの入門記事を見つけることができますが、それでもOSの入門書籍は役に立つと思います。ネットで検索するとディストリビューションが微妙に違ったり、バージョンが微妙に違ったりで「自分の環境に適用出来るか?」を考えなければなりませんが、この本は非常に網羅的に書かれていますので順序立てて学習することができます。

さらに、Fedora 17という比較的最近の2012年5月にリリースされたOSに準拠していることも特徴です。実はネット上の記事の多くはこのバージョンに追いつけていません。Fedoraは最近になって、プロセス管理がinitからsystemdに変更になりましたが、その新しい方法を説明しているのは非常に限られています。もし仕事でLinuxを使うならば、Red Hat Enterprise Linux や CentOS などを使う可能性がありますが、次のバージョン 7 では同じくsystemdが採用されるので、その予習にもなります。

Red Hat系Linuxを学習する最初の一冊としておすすめです。

Linuxのことは知ってる、という方へ

少しLinuxを知っている人がこの本を読んだ場合は、知識の網羅性の確認になると思います。

前述のとおりsystemdの解説はネット上にもほとんどありません。Systemd入門(1) - Unitの概念を理解するというのが日本語で書かれた数少ない記事ですが、実はこの記事を書いた方がこの本の著者です。systemdの解説は7ページほどしかありませんので、あくまで他の記事と合わせて、になります。

他にもSELiunx, setuid/setgid/sticky ビット、find -mtime の -2, 2, +2 の違いなど中級者が「少し自信がないかも」というような内容もカバーされてます。意外とググりながら勉強していく方式だと、自分が直面した課題以外は見過ごされがちなので、そういう方にも使っていただけると思います。逆に今上げたキーワードはわかってるよ、というレベルの方には物足りないと思います。

また、50ページ程度がSamba, PostgreSQL, Railsのインストールと設定に割かれているので、OSのインストールは出来たけれどこのあたりをやったことがないよーという人にも役に立つと思います。

まとめ

  • Linux初学者のために最適
  • 学んだ内容は次のRHEL7にも生きる

2013年10月10日木曜日

MariaDB / MySQL コミュニティイベント in Tokyoに参加しました

10月9日に秋葉原で開催されたMariaDB / MySQL コミュニティイベント in Tokyoに参加してきました。最近話題の MariaDB、いったいどんな感じだろう?という情報収集に出かけました。

MySQL と MariaDB の歴史

  • MySQL は1995年生まれ。MySQL=会社=ソフト
  • 2007年、10億米ドルで Sun が買収
  • 2009年、MariaDB が fork
  • 2009年、Oracle が Sun を買収
  • 2010年、Oracleからコンサルと営業部隊が抜けてSkySQLを創業
  • 2013年、SkySQLとMariaDB Services(エンジニア部隊)が経営統合

SkySQL ABについて

SkySQLはMySQLとMariaDBのサポートを提供している会社。MariaDBの開発にもコミットしているが、MariaDBの運営自体は MariaDB Foundation によって行われている。これはまた買収されることを防ぐため。

ドメインは

  • mariadb.com: Enteprise サービス
  • mariadb.org: MariaDB コミュニティ、Foundation管理

となっている。

顧客満足度は高いと考えている。93%のサブスクリプション更新率を誇る。

MariaDB について

MariaDBの誕生から44ヶ月で、もうすぐ10.0がリリースされる予定。特徴は

  • MySQL との互換性を確保
  • バイナリを置き換えるだけで移行できること
  • 100% GPLv2

バージョン 10.0 は MySQL 5.5 ベース。これは Oracle MySQL 5.6 がリリースされた時に Oracle が過去のコミット履歴をリファクタリングして一部消してしまったため。機能は独自実装を含め、5.6 のスーパーセットを目指している。

私が個人的にいいなと思った機能は

  • Multi-source replication: 一つのスレーブに複数のマスタからレプリケーションする
  • Optimizer がかなり良くなってる(特にJOINやサブクエリ)
  • スレッドプール(Oracle版では有償)
  • SHOW EXPLAIN を使って実行中のクエリに対して EXPLAIN が発行できる
  • group commit によってfsyncを呼ぶ頻度が減った
  • FusionIO DirectFS をサポートし、atomic write できるようになってる
  • GTIDを有効にするときに、全部を一度に切り替えず、徐々にノードを入れ替えられる

あたりです。MySQL でも使えるのかは調べてないので、MySQLでもサポートしていたらご指摘ください...

クライアントライブラリはLGPL版が用意されている。ただしプロトコルは現在のところ互換性があるので、LGPLでなくても良いのであれば無理に移行する必要はないとのこと。

その他、MariaDB Galera Cluster や TokuDB のサポートという言葉が飛んでいて、このあたり知らないので今度調べてみようと思います。

サポートはリリース後5年間提供していて、これは各distributionがMariaDBに移行した理由の一つだと考えている。

MariaDB Manager について

MariaDB をモニタリング、設定、プロビジョンするためのツール群で、シェルスクリプトとPHP、Javaを組み合わせて実装されている。オープンソースで提供される。現在はまだ開発中。

GUIを使っても良いし、RESTful APIを使って既存のツールと組み合わせて利用することも可能。

興味深いと思ったのはスレーブの追加やバックアップもAPIからできるようになっていると言っていたところです。Xtra Backupと組み合わせて使ったりするのか、それとも似たような機能が独自で実装されるのか、そのあたり気になりました。

MaxScale について

MySQL Proxy のような、クライアントとサーバーの間に挟むプロキシを開発中。C言語で、Event-basedで開発しているので高い性能を出せる。従来のプロキシより高機能なものを目指している様子。

  • master-slave、マルチマスタ構成をサポート
  • Sharding のサポート(将来的にはMariaDBの改良とセットでSQLをフルサポート)
  • 各ノードにslaveとして接続し、binlogの進み具合を見て一貫性を保証する仕組み
  • PAM, LDAP, Keystone などの認証をサポート
  • 将来的にはMariaDBのパーザーを載せ、サーバーとの通信をバイナリプロトコルにすることも検討

開発はまだ初期段階で、10月22日にgithubで公開予定なので、フィードバックをくださいとのこと。

全体を通した感想

OracleがMySQLのプロプライエタリライセンスを持っている以上、すべてをGPLで提供するしかないのでどの程度ビジネスが上手くいってるのかなぁと気になって、「いいことばっかりのように思うけど、フリーランチは無いはずで、何を利用者に求めてるの?」と聞いてみました。そしたら「まずはOSSとして開発が進み、フィードバックやパッチがもらえること。もちろんサブスクリプションを買ってもらえるとうれしい」とのことでした。今日聞いただけの話ですが、開発自体はかなりオープンに進めているようで好印象でした。商用版を使っているかどうかで、Oracle MySQLとMariaDBを比較した時の印象は大きく変わるんじゃないかなぁと思います。

テストケースをつけてリリースしていることも強調していました。Oracle MySQL 5.6.14 にはテストケースがひとつも追加されずリリースされたことを引き合いに、オープンソースとしてはMariaDBのほうが参画しやすいのではないか、また、バグトラッカーも一本化していると言っていました。なるほど、普通のオープンソースの開発にかなり近いようです。また、Perconaとは密な協力関係でやっていると言っていました。

今のところRDBMSといえばMySQLという感じですが、PostgreSQLもかなり進化しているし、MariaDBも評価され始めているようなので、一度フラットにいろいろ調べてみるのが良いのかなぁ、と思いました。

「今MySQL 5.6を使ってるんですけど」という話をしたら「MariaDB 10.0が来春に出る予定なので、それまで評価を進めてもらって、その時に移行するかどうか検討するのが良いのではないか」とのことでした。

MaxScale や MariaDB Manager はまだ開発の初期段階で実用は難しそうですが、便利そうではあるのでこの先どういうふうに開発が進むのかなぁと興味を持ちました。

2013年10月7日月曜日

ISUCON3 に参加して予選敗退したので反省してみる

ISUCON3に会社の方と3人でチームを作って参加しました。結果は... 予選敗退! スコアは初期状態のGoで測ったものが最終スコアです...

当日の流れ

今年初参加で、全く予習をしていなかったので勘所もなにもつかめず、まずWebアプリケーションがいくつか転がっていることを認識。言語は議論の末皆がやったことのある Perl に決定。 Perl の会社に務めているのに私だけ Perl がろくに書けません。

作戦は、まずコードを読んでボトルネックになっていそうなところを修正しようとして、コード分析から始めました。具体的には以下の様な点があがりました。

  • markdown を毎回 fork して変換しているのは遅そう
  • ログインしていない状態のページはキャッシュできそう
  • pager は怪しいけど後回しかな
  • 静的ファイルも後ろに投げているのでリバースプロキシで処理しよう
  • SQLにインデックスがなかったり、MySQLがデフォルトで動いているのをなんとかする?

それで、作戦としては基本的にはコンテンツから静的ファイルを作成して nginx の rewrite でがんばろうという話になりました。

最初に想定したアーキテクチャ

初期段階で「このアーキテクチャで行こう」となったものは次のような感じです。

フロント nginx
静的ファイルをサービスする
Webアプリケーション
markdown への変換と動的コンテンツの提供
バックグラウンドWorker
Webアプリケーションから受け取ったデータで静的ファイル生成&DB更新
memcached
アプリケーションとworkerから参照するキャッシュ
RabbitMQ
更新があった時にworkerに仕事を投げるqueue

いま考えると少し大掛かりすぎるわりには全体をカバーできていないアーキテクチャでした。

つまづいたところ

私の担当はworkerだったので、Queueからfetchして静的ファイルを生成するところを作成しだしました。 RabbitMQ との接続には Net::RabbitFoot を使いました。まずはトップページだけ... と思ってやって、ボチボチ出来かけたところで...

  • uri_for で URI 生成しているけど裏workerだと使えない
  • ページにユーザー情報埋め込んでるけど取ってこれない
  • っていうかセッション情報入ってる... 静的にして大丈夫?(いまさら

のようなところで悩み、うまく行かなくなって「ごめん、やっぱり無理...」と断念しました。

その後はいろんなページをmemcachedでキャッシュする方向に進みましたが、なかなか思うように成果が出ず時間切れで終了しました。

こうしたらよかったかな

  • チームで得意言語が違うとそれなりに不利なので、得意言語は合わせるorちゃんと予習したほうがいい
  • 全部を一度に作りなおす方法だとハイリスクなので、少しずつチューニングするほうが失敗した時のダメージが少ない
  • もっと積極的にbenchmark回せばよかった。つねにgit pullしてbenchmarkだけ回し続けるようにしてもいいくらい
  • プロファイリングしたのが午後4時ぐらいで、遅すぎた。
  • いろんな罠が仕掛けられている可能性を考慮すべきだった。
  • ベンチツールがどんなクエリを投げているのか統計とるべきだった

罠というのは、たとえば memcached が 11212 で上がっている問題がありますが、これは自分でmemcachedの設定を書き換えていて、「あれー、反映されない!」となっているのに気付かず、 stats とった時の値がおかしいのに気づかず... というので、自分の設定ミスばかり疑っていました。また、「DOMを変更しないこと」とあったので、スタイルシートの指定にトップページがあるのは気づいていましたが、変更できない... と諦めていました。

memcached 作戦はそこそこ動いて、testでスコア5000ぐらいまで行ったのですが「testは通るけどこの場合にうまくいかない」みたいなケースを見つけてしまいやり直して泥沼にハマってしまいました。多少FAILしても積極的にbenchmarkをとる作戦のほうがよかったと思います。

でも最大の失敗は、コードを中途半端に読んでボトルネックを「推測」するだけに終わり、最初からプロファイリングしたりシステムメトリックスを取得してチューニングに挑まなかったことだと思います。こんなですが会社ではチューニングもやってます...

次回があるとしたら、すぐにgangliaを入れれるようにしておいて基本的な数値は常に見ながらやるようにしようかなぁ、と思いました。あとNYTProfのようなツールの使い方をもっと覚えないといけませんね。

あと一人一インスタンスだったのでChefで構築しようとして途中で諦めてさらに時間をロスしていました。

くやしい

くやしいです...

2013年10月4日金曜日

nginxのsetディレクティブはrewriteモジュールに属する罠

nginxでは変数をセットするときにsetディレクティブを使います。例えば

set $script "";
set $path_info $uri;

というようにです。ところで、このsetディレクティブはngx_http_rewrite_moduleに属します。 つまり、rewrite と組み合わせて

location /download/ {
    rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
    set $script "";
    set $path_info $uri;
    fastcgi_pass unix:/tmp/fastcgi.sock;
}

なんていうことをしていると、rewriteが発動してbreakされた瞬間にrewriteモジュールの評価が終わってしまい、setされません。

location /download/ {
    rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3;
    set $script "";
    set $path_info $uri;
    break;
    fastcgi_pass unix:/tmp/fastcgi.sock;
}

というふうに、breakする場所をsetの後にする必要があります。

ハマりました。