恥知らずのウェブエンジニア -web engineer, shameless

これは一歩を踏み出すことができない者たちのブログ

New Relic ハンズオン・ワークショップ in Tokyoに行ってきた

newrelic.com

行ってきてみました。

new relic使っているものの、transactionからどの処理が遅いか的な使い方しかしてなかったので。

f:id:ogataka50:20160531125042j:plain

スピーカーはNew Relic の Joe LoCascio さん。前編英語かと思いきやしっかり通訳の方がいらっしゃって一安心。

アジェンダ

f:id:ogataka50:20160531131604j:plain

ざっくりメモ

new relicの大枠の機能

  • APM

    • サーバー側のプロファイリング
  • BROWSER

    • フロントエンド側のプロファイリング
  • SYNTHETICS

    • サーバーの死活監視。ブラウザテスト的なこともできるらしい
  • MOBILE

    • ネイティブアプリのプロファイリング
  • SERVERS

    • サーバーのリソース監視
  • PLUGIN

  • INSIGHTS

    • new relicで収集したデータをSQL的な感じ抽出してデータ分析できる

apdex

  • レスポンスタイムからユーザ満足度を図った数値

  • 基準レスポンスタイムを設定し、そこから割合判定

  • apdex計算式

    • apdex = (satisfied + (tolerating / 2)) / total requests

    • satisfied -> 満足。レスポンスタイムが基準値以下

    • tolerating -> まあまあ。基準値の4倍以下

    • flustrated -> 不満足。基準値の4倍以上

key transaction

  • 特定のtransactionをkey transactionに設定することでより詳細な情報を取得できるようになる

  • x-ray sessionで関数レベルで分析できる

    • あとから調べたら現状Java, Python, Rubyのみ対応の模様・・・

error analytics

  • クラスごと、トランザクションごとグルーピングできる
  • error traceもできる
  • newrelicのモジュールを追加すれば、newrelic専用エラー出力もできる

newrelicのAPIでデプロイメントマーカーを設定できる。

  • リリース前後での変化を可視化

custom dashboard

  • 監視したい情報を自分用にピックアップできる

using alerts

  • アラートポリシー設定可能

  • アラート条件、通知チャンネル柔軟に設定可能

所感

  • やろうと思えばもろもろ監視系すべてイケるっぽい

    • でもすでにmuninとかもあったり、他の監視ツールとの住み分けなり統合なり考えないといけなそう
  • 色々できそうだけどnewrelicのオーバーヘッドはないのだろうか・・・

    • 過去にnew relicからマスターDBへ定期的にデータ取得してたりとかあった

    • 野良のプラグインとか要調査が必要そう

  • どうやらもろもろphp対応は後回しの模様・・・

    • 最近風当たりの強さを感じる
  • 頂いたnew relic Tシャツが意外とアグレッシブ

f:id:ogataka50:20160531215105j:plain

でした!

crontabのエラー、(CRON) bad minuteはただの改行の場合でも出る

タイトルでもうほぼ終了なのですが、 crontabを更新した後に、cronのエラーログ/var/log/cronを確認すると下記のエラー

Feb 23 13:29:01 localhost crond[4436]: (xxxxxx) RELOAD (/var/spool/cron/xxxxxx)
Feb 23 13:29:01 localhost crond[4436]: (CRON) bad minute (/var/spool/cron/xxxxxx)
Feb 23 13:29:01 localhost crond[4436]: (CRON) bad minute (/var/spool/cron/xxxxxx)

書式間違っちゃったかなと思い、確認するも明らかに正しいはず・・・ 試しに全てコメントアウトしても上記のエラーが出る始末

よくよく見るとエラーの数と改行の数が一緒 crontabを改行なしにしてみると、エラーは出なくなりました

もうちょっとそれっぽいエラーにして欲しかった感。。。

golangでcrontabからドキュメントを作成するコマンドラインツール crondocを作った

javadoc,phpdoc的にcrontabからドキュメントを生成するツール
crondocをgolangでつくってみました

きっかけ

いくつかのサーバーの設定、ミドルウェア変更することになり、
影響範囲を確認していたのですが、サーバーごとにcronの運用が統一されていなかったのでcronまわり影響範囲を確認するのに時間がかかってしまいました

そこでcronの運用フローを統一する過程でcronの簡単なドキュメントを作成したくなりました

その際、javadoc,phpdocのcron版みたいのがないか探してみたのですが、ないようなのでせっかくなので自作してみました

crondocの機能

ざっくり下記のような機能で作ってみました

  • 標準入力、ファイル指定でcrontabからドキュメントを出力
  • 改行までをひとグループとしてドキュメント出力
  • ドキュメントを出力はmarkdowm形式
  • @authorなどのタグ付ができる

出力例

現状下記のようなcrontabの場合はこんな感じです

  • crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

# @title monday.sh
# @author hoge
# @param env[dev|stg|prod]
# start every monday
0 10 * * 1 sh /home/hoge/happy_monday.sh prod

↓↓↓

Environment variable

- SHELL=/bin/bash
- PATH=/sbin:/bin:/usr/sbin:/usr/bin
- MAILTO=root,hoge@mail.co.jp
- HOME=/

monday.sh

  • Author : hoge
  • param : env[dev|stg|prod]
  • start every monday
min hour day month day week command
0 10 * * Mon `sh /home/hoge/happy_monday.sh prod`

使い方

ソースはこちら
github.com


バイナリを落としてきて、下記のようにすればドキュメントが出力されるはずです

$ crodoc /etc/crontab
$ crontab -l | crodoc -s

まとめ

cron周りはあまり触る回数、人も多くなく属人化しやすい箇所なのでフロー、ドキュメント共有して見える化していければ


せっかく作るならコマンドっぽくしたいってだけでgolangで作ってみたのですが、
わからないこと多く時間かかったし、全然golang的な書き方できてないがいい経験になった。今後も継続!



感謝致します


f:id:ogataka50:20160219114823j:plain

続 サービス稼働中に不要なDBのテーブルを安全に削除する方法

前回の続編です。

youngforever.hatenablog.com

前回まで

前回はdropするテーブルのデータファイルにハードリンクを貼ることでdrop時にファイル削除されることを回避することができました。

しかしioniceで優先度を下げても、巨大なテーブルのデータファイルなどを削除する際はCPU使用率など見る限り負荷がかかっていました。 ioniceは緩やかに削除というより実行の順番の優先度を下げるという挙動のようです。

なので、次に負荷をかけずに巨大なファイルを削除するということで下記を参考にさせてもらいました。 www.nari64.com

truncateコマンドで徐々にファイルサイズを削り、小さくした後に削除するというやり方です。

安全にテーブルdropする手順

まとめて下記のような流れで処理しました

  • 削除前に念のため、dump取る
mysqldump DB_NAME hoge_table > dump_hoge_table.sql
  • 対象テーブルのデータファイルにハードリンクを貼る
ln /usr/local/mysql/data/DB_NAME/hoge_table.ibd /root/hoge_table.ibd
ln /usr/local/mysql/data/DB_NAME/hoge_table.frm /root/hoge_table.frm
  • drop tableを実行
mysql DB_NAME -e "DROP TABLE hoge_table"
  • ハードリンクを貼ったファイルをtruncateコマンドで徐々にサイズを削った後に、rmを実行
//ファイルサイズ取得
$file_size = 0;
$cmd    = "du -m {$file_path} | awk '{print $1}'";
exec($cmd, $output, $ret);
if($ret == 0) $file_size = $output[0];

//truncateで徐々に切り詰める
if($file_size){
  $i = 1;
  while ($i <= $file_size) {
    $tmp_size = $file_size - $i;
    $cmd    = "truncate -s {$tmp_size}M {$file_path}";
    exec($cmd, $output, $ret);
    //0.1sec sleep
    usleep(100000);
    $i++;
  }
//ファイル削除
$cmd = "rm {$file_path}";
$res = exec($cmd, $output, $ret);

的な感じで、稼働中の本番DBで百数テーブル、260GB程度削除しましたが、負荷なく実行できました。 そこそこ時間はかかりますが、、、truncateの部分はもっと攻めて良さそうですがそれはまた次の機会に・・・

これでどんどん不要なテーブル消せますね!

感謝致します。

f:id:ogataka50:20151020111355j:plain

サービス稼働中に不要なDBのテーブルを安全に削除する方法

担当サービスのDBサーバーのディスク容量の空きが少なくなり、不要なテーブルを削除することになりました。
対象のテーブルのデータ量が多く、平常時でもそこそこ負荷のあるサーバーなのですが、
テーブル削除だけのためにメンテナンスをするのもアレなので、
深夜帯にしれっとdropしたい気持ちを抑えつつ、負荷のかからないdrop tableの手順を試してみました。

サービス稼働中にテーブルdropする時の問題点

metadata lock

drop対象のテーブルに書き込みやトランザクションが貼ってあるとmeta data lockがかかってしまいます
今回は参照等がないテーブルなので、問題なし

巨大なファイルを削除するとI/O待ちが発生する

巨大なテーブルのデータファイルを削除すると他のプロセスがI/O待ちになる可能性があります

安全にテーブルdropする方法やってみた

完全にこちらを参考をさせて頂きました。

qiita.com

dropする前にデータファイルにハードリンクを貼り、
drop時はファイル削除を行わず、後に優先度を下げて実ファイルを削除するという流れです。


さっそく本番でもやってみました。

# データファイルにハードリンクを張る
ln /usr/local/mysql/data/hoge_db/bk_hoge_tbl.ibd /home/hoge/bk_hoge_tbl.ibd


time mysql  -e "DROP TABLE bk_hoge_tbl"
real    0m0.047s
user    0m0.002s
sys     0m0.002s


time ionice -c 3 rm -f /home/hoge/bk_hoge_tbl.ibd
real    0m14.505s
user    0m0.001s
sys     0m0.065s

確かに意図通り、dropはデータ量に限らず一瞬で終わり、
データ削除はデータ量によって実行時間に違いがありました。

が、、、drop中は問題ありませんでしたが、データ削除中に若干レスポンスの悪化が見られました。


巨大なファイルを低負荷で削除する方法

結局、巨大なファイルを削除する時のI/O待ちが問題なら
drop前にパーティション切ってデータ細切れにするのはどうかな?でもめんどいなーって思っていたら下記の記事を見つけました。

www.nari64.com

巨大なファイルを削除する方法

このケースが一番悩まされました。しかし、最近 truncate コマンド使えばいいのでは〜ということに気がつきました。

truncate コマンドを用いて少しずつファイルサイズを減らす
sleep をはさむ


徐々にファイルサイズを小さくして、削除すればI/O負荷軽減できそうです。
次回はこちらの手順で削除してみようかと思います♪





感謝致します。

f:id:ogataka50:20150922171405j:plain

mysql explain で出てくるSelect tables optimized awayって何ですか?

日次で開発環境で実行されたクエリにEXPLAINをかけて、危なそうなクエリを通知するようにしています。 そこでこんなんが出てきました

mysql> EXPLAIN PARTITIONS SELECT MAX(`hoge_col`) AS total_count FROM `hoge_table`;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+------------------------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Select tables optimized away |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+------------------------------+

index貼られてないー><

index貼る

mysql> EXPLAIN PARTITIONS SELECT MAX(`hoge_col`) AS total_count FROM `hoge_table`;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+------------------------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Select tables optimized away |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+------------------------------+

変わらず・・・

そこでよくよく確認すると、hoge_colはprimary_keyになっていました。

で、今度は「Select tables optimized away」はなんだと。

ドキュメントを確認すると、

MySQL :: MySQL 5.6 リファレンスマニュアル :: 8.8.2 EXPLAIN 出力フォーマット

Select tables optimized away

クエリーにはすべてインデックスを使用して解決された集約関数 (MIN()、MAX())、または COUNT(*) のみが含まれていますが、GROUP BY 句は含まれていませんでした。オプティマイザは 1 行のみを返すべきであると判断しました。

オプティマイザが良きにはからってくれた結果だそうです。 内部的にはインデックスを使っているようなので、負荷等は問題なさそうです。ほぼ最速の模様。



感謝致します。 f:id:ogataka50:20150808232205j:plain

1分でできる!mysqlslapでDBのかんたん性能調査、ベンチマーク

業務中にそこそこ大きなスキーマ変更をすることになり、実際パフォーマンスに変化があるかベンチマークを取る必要が出てきました。


jmeterとかでごりょごりょとかしないとなのかーとか思ったのですが、 今回はスキーマ変更のみなので、単純にDBのみの測定でよいので、なんかいいツールはないかと探したところ、

mysqlslapなるものがあるようなので試してみました


MySQL :: MySQL 5.7 Reference Manual :: 4.5.7 mysqlslap — Load Emulation Client

MySQLクライアント負荷エミュレーション mysqlslap を使う - Qiita

mysqlslapはMySQLサーバのクライアント負荷をエミュレートし、各ステージのタイミングを報告する診断プログラムです。サーバにたいして複数のクライアントがアクセスしているかのように作動します。mysqlslapはMySQL 5.1.4.から提供されています。

さっそく試してみーる

使い方

mysqlがインストールされていれば標準でmysqlslapもインストールされているはずなので、すぐ使えます

基本的には、測定する際特定のスキーマを作って、テキトーなクエリを実行してベンチマークを取る感じのようですが、 今回は実際の本番相当のデータ量のテーブルを用意し、それに対して測定を行いました。

#測定するSQL
SELECT * FROM TMP_TABLE WHERE hoge = 'hoge'
/usr/local/mysql/bin/mysqlslap\
 --no-defaults\
 --user=USER\
 --password=PASS\
 --host=localhost\
 --port=3306\
 --engine=innodb\
 --concurrency=500\
 --iterations=30\
 --create-schema=TMP_DB\
 --query="SELECT * FROM TMP_TABLE WHERE hoge = 'hoge'"


Benchmark
        Running for engine innodb
        Average number of seconds to run all queries: 0.755 seconds
        Minimum number of seconds to run all queries: 0.702 seconds
        Maximum number of seconds to run all queries: 0.795 seconds
        Number of clients running queries: 500
        Average number of queries per client: 1

的な感じでベンチマーク取れます! 500回SELECTするのを30回行い、それらの最大最小平均が取れます

オプション
オプション 内容
no-defaults 設定ファイルに書かれたデフォルトをスキップ
user 接続ユーザ
password パスワード
host mysqlのhost
port mysqlのpoot
engine 対象ストレージエンジン
concurrency シミュレートする実行の数
iterations 実行するテストの回数
create-schema テストを実行するスキーマ
query 実行するクエリ(ファイル指定も可能)

今回は作成済みのDB、テーブルに対して実行したのですが、 他にもテキトーなクエリを自動生成して、ベンチマークを取ることもできるようです。 というかそのほうが本来の使い方っぽいですね。。。

設定ファイルいじって性能確認する的な。



ともあれとってもお手軽!

ベンチマークというと手間かかるなーと思いがちですが、 これなら、実装後にさくっと確認できていい感じです!

もっと早く知りたかった・・・!




感謝致します。

f:id:ogataka50:20150708173637j:plain