2013-11-19
CentOS 5+Tomcat 7+JDK 7+Apacheという組み合わせで動かしていたサーバ群に、OSだけCentOS 6にしてミドルウェアのバージョンは変えないサーバを何台か追加したところ、CentOS 6の方が、Tomcatが確保している仮想メモリ量が圧倒的にでかいことに気づいた。
ちなみに、どちらのサーバもヒープサイズは「-Xmn1024m -Xmx2048m -Xms2048m」となっており、本来なら2GBプラスアルファ(コードキャッシュ他の領域分)しかメモリは食わないはずだ。もちろん、ロードバランサではどちらのサーバにも同じ重みでアクセスを流していおり、負荷は同じのはず。
CentOS 5のサーバ
こちらはざっくり3GB弱の仮想メモリを確保していると出ている(左から5番目、VSZの列)。ヒープサイズから考えるとまあこんなものかというレベル。
# ps auwx
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
31234 10315 110 8.8 3134280 1447956 ? Sl Nov14 6870:09 /usr/local/java/bin/java -Djava.util.logging.config.file=/usr/l cal/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -server -XX:MaxPermSize=128m -XX:PermSize=128m -XX:SurvivorRatio=2 -Xmn1024m -Xmx2048m -Xms2048m (後略)
CentOS 6のサーバ
一方こちらは10GB弱ものメモリを確保していることになっている。ヒープサイズとの差分9GB近くはどっから出てきたのか?
# ps auwx
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
31234 19463 156 33.6 11270576 2708744 ? Sl Nov14 9532:10 /usr/local/java/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -server -XX:MaxPermSize=128m -XX:PermSize=128m -XX:SurvivorRatio=2 -Xmn1024m -Xmx2048m -Xms2048m (後略)
CentOS 6の方のサーバのTomcatのプロセスIDを指定してpmapコマンドでメモリの確保状況を見てみると、何やら同じ容量(64MBぐらい)を確保しているanonという行がたくさん表示されているのが目につく。これが悪さしているようだ。ちなみに、一番右の列には通常そのメモリを確保しているファイル名が出るが、anonというのは匿名で割り当てのみがされた領域を示しているようだ。
# pmap -x 19463 | sort -k2 -n
Address Kbytes RSS Dirty Mode Mapping
(略)
00007f08d0218000 63392 0 0 -- [ anon ]
00007f0878215000 63404 0 0 -- [ anon ]
00007f099c208000 63456 0 0 -- [ anon ]
00007f08941fe000 63496 0 0 -- [ anon ]
00007f09341fb000 63508 0 0 -- [ anon ]
00007f091c1ea000 63576 0 0 -- [ anon ]
00007f08901e5000 63596 0 0 -- [ anon ]
00007f08fc1e3000 63604 0 0 -- [ anon ]
00007f09c01e0000 63616 0 0 -- [ anon ]
00007f094c1d8000 63648 0 0 -- [ anon ]
(略)
調べてみたところ、この現象は、CentOS 6に含まれているglibc 2.11の挙動によるものだそうだ。glibc 2.10から、スレッドごとにメモリ空間を割り当てるような実装に変わったとのこと。なお、CentOS 5ではglibcは2.5。以下、glibcのコミッタUlrich Drepper氏による2.10のchangelog解説 からの抜粋。
glibcに対する今回の変更では、スレッドごとにメモリプールを作るようになった。これで多くの場面で間違った割り当てを排除することができる。メタデータは通常1つのスレッド内でしかアクセスしない(スレッドは割り当てられたコアから移動されないのが望ましい)。アドレス空間を吹き飛ばしてしまうようなメモリのハンドリングを防ぐため、メモリプールの使い過ぎに上限が設けられた。デフォルトでは、32ビットマシンではコアあたりメモリプール2つ、64ビットマシンではコアあたりメモリプール8つを生成する。
プールが確保するサイズは64MBであり、上の例のCentOS 6のマシンの場合、CPUは24コアの64ビットマシンなので、「24コア x 8 x 64MB」が仮想メモリとして確保されているため、VSSの列の値が大きくなっていたというわけだ。なお、このプール用のメモリはあくまで割り当てられただけで使用されているわけではない。そのため、実際に使われているメモリはRSS(Resident Set Size)の列に表示されているものである(当然だが)。
Tomcat動かしてて気づいたのでタイトルが「TomcatのJVMが~」となっているが、同じようなつくりのメモリを大きく確保するアプリケーションでは同じことになるのは言わずもがな。
参考1 : Quoraのやりとり「なぜいくつかのアプリケーションはRHEL5と比べてRHEL6では明らかに大きな仮想メモリを使うのか?」
参考2 : IBM developerWorksの記事「Linuxのglibc 2.10以上(RHEL6)のmallocは仮想メモリの使用量を過大に表示するのか」
参考3 : StackOverflowのやりとり「Linux上でのJavaの仮想メモリ使用量が大きすぎる」
解説が非常に詳しくてためになる。
参考4 : 上述glibcコミッタUlrich Drepper氏の記事
2013-10-26
MySQL Casual Talks vol. 5 に行ってきたので、自分なりのメモと資料へのリンク。
途中、アラートが鳴り始めて確認してたりしてメモが適当なところがあるが仕方なしw
かなりのスピードでじゃんじゃんプレゼンが進んで行ったが、どれも面白い・役立つ内容ばかりで、楽しいひと時でした。発表者の皆様、会場の提供や調整などしてくださった@myfinder さんはじめとする皆様、ありがとうございました。自分の隣でビール缶を次々と「カシュッ」と空けていた@oranie さんのような余裕を持ちつつ、次回は自分も何かネタを提供できるといいなあ。
@yuryu さん GTIDを使い始めてやめた話
GTID - 全てのトランザクションを一意に識別、一貫性保証
マスタを切り替えると、マスタのUUIDが変わるのでGTIDが2個になる
利点
change master to … master_auto_position=1で簡単にレプリをはれる
mysql workbenchのmysqlfailoverとか使える
欠点
クラスタ全部GTID有効にする必要
MyISAM使用不可
HAしたいならMHAでいいんじゃね?
バグ
GTID有効でFLUSH LOGSするとレプリ停止(5.6.11のみ)
stop/start slaveするとトランザクションがスキップされる可能性あり
ネットワーク切断でトランザクションスキップの可能性
結局、本格的に使うには時期尚早なので辞めました、ということ
クックパッでは5.5のサーバを5.6にバージョンアップしたり最初から使ったり
レプリしてクエリ流してコンフィグいじり始めた
EBSでスナップショット取ったボリュームを5.6マシンにぶら下げてmysql_upgrade実行
Kage
リクエストをコピーしてsandbox環境に流す仕組み(ユーザへはproductionからの結果が返る)
レスポンスのdiffも取れる
バックエンドを5.6にして違いを確認
バージョン違い、設定違いのサーバを並べて比較
開発用DBを先に新しくしてリリース前に新環境を試す
バグ確認用(最新) → 検証用(1つ前) → 本番用(安定版)
各バージョンが入ったAMIを用意しておいてすぐ起動できるようにしてある
GTID有効だとsql_slave_skip_counter使えない
AWSだと色んな検証がCasualにできる
bugs は見ましょう!
5.6で遅くなるところもあるので、得意な部分から本番投入していっている
@yoshi_ken さん 5.0 Tritonnから5.6 mroongaへの移行
技評の記事 の裏話
旧構成 マスタはDRBDでミラー、スレーブにレプリ
5.6スレーブを追加してそこに孫をぶら下げて旧環境を切り離し
本番環境のアクセスログから抜き出したURLを使ってテスト
テスト中に見つけたmroongaのバグはすぐに修正してもらえた
HWトラブル
マスタ死亡、起動しない、焦げ臭い!さらにもう一台も焦げた。。
GTIDよりsemi sync repl + MHAがいいのでわ
innodb_file_per_tableでなかったのでダンプしてバージョンアップした
memcached APIはバグで使えなかった
@yoku0825 さん アプリ担当が出してきたDDLがドイヒーな話
すごい心が痛い&共感出来る内容だったけどテンポ早すぎてメモできなかったw
MariaDB 10からもGTIDが使えるようになった(ただしMySQLとは結構違う)
ログ用テーブル
インデックス名はidx_カラム名_カラム名_…とすると長いけどexplainのときに分かりやすい
フレームワークが作る通りではなくDBの特性を考える
SQL文を見るだけでどのインデックスを使うかなどの意図が分かる名前付け
プレゼン資料
この辺りトラブル発生してメモがおろそか
いろんなMySQLをインストールして使い分ける仕組み
percona serverのmysqldumpにはkeyを消してダンプして作り直すオプションがある
fbの5.6にはlogical key readのオプションがある
@do_aki さん multi master replication
MySQL Casual定番の内容
change masterを2秒ごとに切り替えてマルチマスタ
5.7では標準でできるようになった
過去に色々な方法でマルチマスタを試みている人がいるww
@RKajiyama さん 5.7 Multi-source replication
labsにはDMR以前のものがありますよ
hadoop applier for mysql
JSON UDF
Multi source replication
MySQL Utilities Fabric
Fabric + multi source replication + multi thread slaveの組み合わせ良さげ
プレゼン資料
GitDDL::Migrator, SQLTranslator(SQLFairy)
ブランチごとにテーブルやカラムが違うと大変
テーブル構成の違いなどが表示できる
ブランチを行ったり来たりしながらalterしたりできる
App::RunCron
perlのラッパー、レポータを書くと色々できる
cronのログってnullに捨てちゃうけど困るよね
cronlog
cronの処理をラップしてエラー処理が可能
13年運用されてるデータベース
レコードをCSVにしてload infile
シェルスクリプトで自動化
4時間以内に終わらせるという時間制約
loadを高速化する工夫
ジョブフローの最適化(jenkins build flow plugin)
ジョブフローをGroovyで書ける(並列実行などなども可)
データ移行自体をCIする(1クリックデータ移行!)
/var/lib/mysql以下の並列rsync
@monry さん Amazon RDS
マスタ1台、スレーブ5台
物理サーバが1台13万以上ならRDSの方が安い(3年償却)
@chobi_e さん ストレージエンジンを作ってみた
2013-10-01
MyNA(日本MySQLユーザ会)会 2013年9月
先週のMySQL Cluster Casual Talksに続いて、週末にかけて行われたMySQL Connect で発表された最新情報を聞けるということで、MyNA会に参加してきた。基調講演の内容は既に報道されていたので(Publickey (1) , (2) , (3) )ある程度分かっていたが、一番うれしかったのはMySQL Fabricのデモが見られたこと。MySQL Utilitiesの機能でシャーディングができるようになるということでどんな感じか見てみたかったので、(ラボ版で一部動かないところがまだあるということだったが)興味深かった。発表者のみなさま、会場を提供していただいたOracleのみなさまなど関係者の方々ありがとうございました。
@RKajiyama さん MySQL Connect基調講演の概要
いつOracleはMySQLを殺すのかと言われてきた → うわさを打ち消すために3年半の間大量のリリースをしてきた
チーム全体も増員、特に品質管理チーム
DMR(Development Milestone Release)というやり方
リリース候補版になったコンポーネントを含んだリリース
18から24ヶ月ごとにメジャーリリースしたい
Webや組み込み系に強いDBとしてOracleにとっても価値 がある
現在もLinux系の最も重要なスキル=MySQL
今もユーザは多数
5.7.2 DMRの発表
Release noteが超長かった=たくさんの更新が含まれている
InnoDBパフォーマンス向上
explain for connectionで別セッションのexplain
Optimzerの結果をWorkbenchでさらに詳しく
performance schema改善
tmpテーブルがInnoに
同じDB内でのマルチスレッドレプリケーション
5.7の以後のバージョンでの予定
MySQL Utilities 1.3
MySQL Utilities 1.4から
Fabric
アプリから意識せずにシャーディングできる
Connectorが接続を受けて振り分ける
レンジかハッシュ、リシャーディング
いちいさん@Gree, いけださん@SCSK MySQL Connectの感想
Oracle OpenWorld、JavaOneと一緒にやってる
SFのホテルいくつも貸し切り、道路も閉鎖して休憩スペースに
FacebookのMySQLの話
まつのぶさん MySQL 5.6@Facebook
5.1にパッチ当てたのを使っている
圧縮、クラッシュセーフスレーブ、フラッシングの高速化など
シャドウサーバ
5.5を飛ばして5.6へ
GoogleがMySQLをやめてMariaDBに全面移行する というのは、XLDBというカンファレンスでの話を元にした記者の煽り記事 で、Googleの人曰く迷惑しているそうだ
MySQL json UDFs
カラムにJSONをつっこんだものをファンクションで処理できる
ラボ版のMySQL Utilities に搭載された新機能
マスタにスレーブがぶら下がってる構成
アプリからConnectorを使ってアクセスする
ConnectorはFabricに問い合わせ先を確認してからシャードにアクセス
state storeに情報保存
スキーマの情報などだけもってデータは持たない
グローバルグループ
アクセス時にRWかROを指定すると、Fabricが自動でマスタあるいはスレーブにアクセスを振る
lab版は罠だらけ なので気をつけよう。。
開発者の方のブログ が役に立つ
赤井さん GNU 30周年とMySQL
GNUプロジェクトが始まって30年
MySQLの成長はGNUの恩恵を受けた
GNUへのリスペクトを忘れないように しよう