読者です 読者をやめる 読者になる 読者になる

256bitの殺人メニュー

インフラエンジニアだったソリューションアーキテクトなくわののブログ。こちらのBlogは個人の意見となっていて会社とは全く関係ありません。お約束です。[twitter:@kuwa_tw]めんどくさがりが重い腰を上げて何かをアウトプットすることにどれほどの意味があるのかを試してみたいブログでもある。

MongoDB3系でWiredTiger使うなら3.0.6以上で使わないと高負荷時に落ちるので注意マン

どうもどうも乙カレー様です。桑野です。
今日はちょっとだけ神妙な面持ち。


MongoDB3系でWT使っている場合に、3.0.6以前のものを使っていたらバージョンアップしましょうって話。

問題

アクセスの増えてきたタイミングから下記のようなログがでてコネクションが溜まってしまう。
その後溜まりすぎてメモリが確保できずにプロセスが落ちる。死。

2015-08-16T09:06:36.012+0000 E STORAGE [conn38726] WiredTiger (12) [1439715996:12678][61157:0x7f105350e700], connection.open_session: only configured to support 20010 sessions (including 10 internal): Cannot allocate memory
2015-08-16T09:06:36.012+0000 I - [conn38726] Invariant failure: ret resulted in status UnknownError 12: Cannot allocate memory at src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp 49
2015-08-16T09:06:36.013+0000 I NETWORK [initandlisten] connection accepted from 192.168.110.196:20692 #47886 (20559 connections now open)
2015-08-16T09:06:36.013+0000 I NETWORK [initandlisten] connection accepted from 192.168.110.196:20693 #47887 (20560 connections now open)
2015-08-16T09:06:36.014+0000 E STORAGE [conn38650] WiredTiger (12) [1439715996:14701][61157:0x7f105815a700], connection.open_session: only configured to support 20010 sessions (including 10 internal): Cannot allocate memory
2015-08-16T09:06:36.014+0000 I - [conn38650] Invariant failure: ret resulted in status UnknownError 12: Cannot allocate memory at src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp 49
2015-08-16T09:06:36.015+0000 E STORAGE [conn31890] WiredTiger (12) [1439715996:15938][61157:0x7f12003c2700], connection.open_session: only configured to support 20010 sessions (including 10 internal): Cannot allocate memory
2015-08-16T09:06:36.015+0000 I - [conn31890] Invariant failure: ret resulted in status UnknownError 12: Cannot allocate memory at src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp 49
2015-08-16T09:06:36.020+0000 E STORAGE [conn38728] WiredTiger (12) [1439715996:20420][61157:0x7f105330c700], connection.open_session: only configured to support 20010 sessions (including 10 internal): Cannot allocate memory
2015-08-16T09:06:36.020+0000 I - [conn38728] Invariant failure: ret resulted in status UnknownError 12: Cannot allocate memory at src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp 49
2015-08-16T09:06:36.021+0000 E STORAGE [conn1438] WiredTiger (12) [1439715996:21384][61157:0x7f12c63f3700], connection.open_session: only configured to support 20010 sessions (including 10 internal): Cannot allocate memory
2015-08-16T09:06:36.021+0000 I - [conn1438] Invariant failure: ret resulted in status UnknownError 12: Cannot allocate memory at src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp 49
2015-08-16T09:06:36.027+0000 I CONTROL [conn2503]
0xf5e199 0xefd1b1 0xee386a 0xd80e50 0xd81326 0xd7c7ce 0xd7c815 0xd6af65 0xa84a08 0xa0eab2 0xa0f1ed 0xa02e8d 0xa25425 0xa10a64 0xbd06b4 0xbd0a64 0xb9ef64 0xab5040 0x80fbad 0xf112bb 0x7f133d722182 0x7f133c1eb47d
----- BEGIN BACKTRACE -----
{"backtrace":[{"b":"400000","o":"B5E199"},{"b":"400000","o":"AFD1B1"},{"b":"400000","o":"AE386A"},{"b":"400000","o":"980E50"},{"b":"400000","o":"981326"},{"b":"400000","o":"97C7CE"},{"b":"400000","o":"97C815"},{"b":"400000","o":"96AF65"},{"b":"400000","o":"684A08"},{"b":"400000","o":"60EAB2"},{"b":"400000","o":"60F1ED"},{"b":"400000","o":"602E8D"},{"b":"400000","o":"625425"},{"b":"400000","o":"610A64"},{"b":"400000","o":"7D06B4"},{"b":"400000","o":"7D0A64"},{"b":"400000","o":"79EF64"},{"b":"400000","o":"6B5040"},{"b":"400000","o":"40FBAD"},{"b":"400000","o":"B112BB"},{"b":"7F133D71A000","o":"8182"},{"b":"7F133C0F1000","o":"FA47D"}],"processInfo":{ "mongodbVersion" : "3.0.4", "gitVersion" : "0481c958daeb2969800511e7475dc66986fa9ed5", "uname" : { "sysname" : "Linux", "release" : "3.13.0-46-generic", "version" : "#77-Ubuntu SMP Mon Mar 2 18:23:39 UTC 2015", "machine" : "x86_64" }, "somap" : [ { "elfType" : 2, "b" : "400000", "buildId" : "32DC52072DB9385642CCB4D2AD2ACDA6E0B87A27" }, { "b" : "7FFFE2AB1000", "elfType" : 3, "buildId" : "88E7559031E488BC215236F4181BD1FAF9A458F0" }, { "b" : "7F133D71A000", "path" : "/lib/x86_64-linux-gnu/libpthread.so.0", "elfType" : 3, "buildId" : "9318E8AF0BFBE444731BB0461202EF57F7C39542" }, { "b" : "7F133D4BC000", "path" : "/lib/x86_64-linux-gnu/libssl.so.1.0.0", "elfType" : 3, "buildId" : "FF43D0947510134A8A494063A3C1CF3CEBB27791" }, { "b" : "7F133D0E2000", "path" : "/lib/x86_64-linux-gnu/libcrypto.so.1.0.0", "elfType" : 3, "buildId" : "379F80D2768BA6A21F52781895EE9F47B34A0A85" }, { "b" : "7F133CEDA000", "path" : "/lib/x86_64-linux-gnu/librt.so.1", "elfType" : 3, "buildId" : "92FCF41EFE012D6186E31A59AD05BDBB487769AB" }, { "b" : "7F133CCD6000", "path" : "/lib/x86_64-linux-gnu/libdl.so.2", "elfType" : 3, "buildId" : "C1AE4CB7195D337A77A3C689051DABAA3980CA0C" }, { "b" : "7F133C9D2000", "path" : "/usr/lib/x86_64-linux-gnu/libstdc++.so.6", "elfType" : 3, "buildId" : "19EFDDAB11B3BF5C71570078C59F91CF6592CE9E" }, { "b" : "7F133C6CC000", "path" : "/lib/x86_64-linux-gnu/libm.so.6", "elfType" : 3, "buildId" : "1D76B71E905CB867B27CEF230FCB20F01A3178F5" }, { "b" : "7F133C4B6000", "path" : "/lib/x86_64-linux-gnu/libgcc_s.so.1", "elfType" : 3, "buildId" : "8D0AA71411580EE6C08809695C3984769F25725B" }, { "b" : "7F133C0F1000", "path" : "/lib/x86_64-linux-gnu/libc.so.6", "elfType" : 3, "buildId" : "30C94DC66A1FE95180C3D68D2B89E576D5AE213C" }, { "b" : "7F133D938000", "path" : "/lib64/ld-linux-x86-64.so.2", "elfType" : 3, "buildId" : "9F00581AB3C73E3AEA35995A0C50D24D59A01D47" } ] }}
mongod(_ZN5mongo15printStackTraceERSo+0x29) [0xf5e199]
mongod(_ZN5mongo10logContextEPKc+0xE1) [0xefd1b1]
mongod(_ZN5mongo17invariantOKFailedEPKcRKNS_6StatusES1_j+0xDA) [0xee386a]
mongod(_ZN5mongo17WiredTigerSessionC1EP15__wt_connectionii+0xA0) [0xd80e50]
mongod(_ZN5mongo22WiredTigerSessionCache10getSessionEv+0x4C6) [0xd81326]
mongod(_ZN5mongo22WiredTigerRecoveryUnit10getSessionEPNS_16OperationContextE+0x3E) [0xd7c7ce]
mongod(_ZN5mongo16WiredTigerCursorC1ERKSsmbPNS_16OperationContextE+0x35) [0xd7c815]
mongod(_ZNK5mongo23WiredTigerIndexStandard9newCursorEPNS_16OperationContextEi+0x55) [0xd6af65]
mongod(_ZNK5mongo22BtreeBasedAccessMethod9newCursorEPNS_16OperationContextERKNS_13CursorOptionsEPPNS_11IndexCursorE+0x28) [0xa84a08]
mongod(_ZN5mongo9IndexScan13initIndexScanEv+0x62) [0xa0eab2]
mongod(_ZN5mongo9IndexScan4workEPm+0x4D) [0xa0f1ed]
mongod(_ZN5mongo10FetchStage4workEPm+0xCD) [0xa02e8d]
mongod(_ZN5mongo16ShardFilterStage4workEPm+0x55) [0xa25425]
mongod(_ZN5mongo10LimitStage4workEPm+0x54) [0xa10a64]
mongod(_ZN5mongo12PlanExecutor18getNextSnapshottedEPNS_11SnapshottedINS_7BSONObjEEEPNS_8RecordIdE+0xA4) [0xbd06b4]
mongod(_ZN5mongo12PlanExecutor7getNextEPNS_7BSONObjEPNS_8RecordIdE+0x34) [0xbd0a64]
mongod(_ZN5mongo8runQueryEPNS_16OperationContextERNS_7MessageERNS_12QueryMessageERKNS_15NamespaceStringERNS_5CurOpES3_+0xA74) [0xb9ef64]
mongod(_ZN5mongo16assembleResponseEPNS_16OperationContextERNS_7MessageERNS_10DbResponseERKNS_11HostAndPortE+0xB10) [0xab5040]
mongod(_ZN5mongo16MyMessageHandler7processERNS_7MessageEPNS_21AbstractMessagingPortEPNS_9LastErrorE+0xDD) [0x80fbad]
mongod(_ZN5mongo17PortMessageServer17handleIncomingMsgEPv+0x34B) [0xf112bb]
libpthread.so.0(+0x8182) [0x7f133d722182]
libc.so.6(clone+0x6D) [0x7f133c1eb47d]
----- END BACKTRACE -----
2015-08-16T09:06:36.027+0000 I CONTROL [conn38518]
0xf5e199 0xefd1b1 0xee386a 0xd80e50 0xd81326 0xd7c7ce 0xd7c815 0xd6af65 0xa84a08 0xa0eab2 0xa0f1ed 0xa02e8d 0xa25425 0xa10a64 0xbd06b4 0xbd0a64 0xb9ef64 0xab5040 0x80fbad 0xf112bb 0x7f133d722182 0x7f133c1eb47d

原因

この あたり のISSUEに上がってる物が原因

対応1:cursorTimeoutを伸ばす

cursorTimeoutを伸ばす事で回避できるよってあったんでこちら入れてみた。

mongo> use admin
mongo> db.runCommand({setParameter:1, cursorTimeoutMillis: 60000})

全く変わらず。

対応2:シャード増やす

一定以上のアクセスが来なければおこらないはずなので、一時的にシャード増やしてみた。

対応は可能だった、一定の効果は(当たり前)だけどコストが(;´∀`)
まあ一次対応としてはアリ。

対応3:対応後のバージョンに上げる

3.0.6で対応されたから試してみてよって前述のISSUEにあったので満を持してバージョンアップしてみる。
ちなみにMongoDB Cloud Manager(旧MMS)でのバージョンアップは非常に楽チン(ただしMMSには罠がいっぱいあるので癖を覚えるまで辛い)


バージョン上げたタイミングでコネクションが増え続けることもなくなった。
というわけで、新しいのはまだ人柱的な物もよくありますねって話。それもまた楽し。
他の方でも同様の現象で困っている方がいたらバージョンアップ検討しましょう。


バージョンアップ方法はこの辺りが参考になります。


ではでは!


データベース徹底攻略 (WEB+DB PRESS plus)

データベース徹底攻略 (WEB+DB PRESS plus)

キャプテン マンゴー 600ml

キャプテン マンゴー 600ml

Terraformを使ってEC2のAutoScalingやろうとしたらちょっとつらいんじゃないかなってなった話

どうもどうも乙カレー様です。桑野です。
びっくりするほどブログ書いてなくてびっくりしてます。半年書いてないやん。


Terraformを使っていたりするんですが、最近EC2のAutoScaleを入れようとして辛いことがあったりしたのでちょっとまとめてみます。

Terraform

Terraformは言わずとも知れたHashicorpさんのプロダクトですね。
インフラ構築をコード化してGithub等でレポジトリ管理することによって履歴管理や、プルリクエストベースの構築ができるのが売りだったりします。

TerraformでのAutoScale時のハマりどこ

端的にいうとこの2つです。

  • Terraform経由で実行した際のLaunchConfiguration(イカLC)とAutoScalingGroup(イカASG)の削除の順番が逆
  • LC内のuser_data更新で一網打尽になる
Terraform経由で実行した際のLaunchConfiguration(イカLC)とAutoScalingGroup(イカASG)の削除の順番が逆

何が悪いかといいますと、この2つは依存関係があるので、ASGを削除する前にそれが紐付いてるLCを削除しようとするとまだAttachされてるよってエラーが出て止まるわけです。
なので、ASG->LCの順で削除してくれればいいんだけど、実際には逆でしか動いてくれない。

* ResourceInUse: Cannot delete launch configuration launchconfig-test because it is attached to AutoScalingGroup autoscalinggroup-test
        status code: 400, request id: [12345678-1234-1234-1234-123412341234]


となると。

GithubのIssueとかでも同じような議論があってlifecycle { create_before_destroy = true }をつけたらいいぜって言ってる人もいるけど、作成タイミングの違いだからやっぱりうまく動かない。

LC内のuser_data更新で一網打尽になる

じゃあ2個作って交互に更新して行ったらええんちゃうんかでバージョン管理する。
これでOKでしょ。

# 古いLC
resource "aws_launch_configuration" "launchconfig_test_v1" {
  name = "launchconfig-test-v1"
  image_id = "${var.amis.api}"
  key_name = "${var.aws.key_name}"
  instance_type = "t2.micro"
  security_groups = ["${var.security_groups.asgtest}"]
  iam_instance_profile = "asgtest"
  associate_public_ip_address = 0
  user_data = "${file("user_data/app_userdata.sh")}"
}
# 新しいLC
resource "aws_launch_configuration" "launchconfig_test_v2" {
  name = "launchconfig-test-v2"
  image_id = "${var.amis.api}"
  key_name = "${var.aws.key_name}"
  instance_type = "t2.micro"
  security_groups = ["${var.security_groups.asgtest}"]
  iam_instance_profile = "asgtest"
  associate_public_ip_address = 0
  user_data = "${file("user_data/app_userdata.sh")}"
}

ぼくが気付かなかっただけだけど、この場合はuser_data/app_userdata.shが更新されるとどっちも再作成になって⊂ミ⊃^ω^ )⊃ アウアウ!!

* ResourceInUse: Cannot delete launch configuration launchconfig-test because it is attached to AutoScalingGroup autoscalinggroup-test-v1
        status code: 400, request id: [12345678-1234-1234-1234-123412341234]

TerraformでのAutoScale時する時のベストプラクティス?

じゃあどうしたらいいんだって話ですが、一旦色々考えたり話したりした挙句こんな感じになりました。

  • ASG, LC, user_dataはバージョニングする
  • 追加/削除時の作業順を厳密に指定する
    • 1. user_data作成
    • 2. 新LC, ASG作成
    • 3. 旧ASGの desired_capacity を0にして既存系のインスタンス削除する
    • 4. 旧ASGを削除する
    • 5. 旧LCを削除する

この手順だと実際にApplyするのは、2. 3. 4. 5.で4回です(2. と3. はまとめられますがそれでも3回)。多いですね。

3.の時の設定の状態
# 古いLC
resource "aws_launch_configuration" "launchconfig_test_v1" {
  name = "launchconfig-test-v1"
  image_id = "${var.amis.api}"
  key_name = "${var.aws.key_name}"
  instance_type = "t2.micro"
  security_groups = ["${var.security_groups.asgtest}"]
  iam_instance_profile = "asgtest"
  associate_public_ip_address = 0
  user_data = "${file("user_data/app_userdata_v1.sh")}"
}
# 古いASG(この後削除する)
resource "aws_autoscaling_group" "autoscalinggroup_test_v1" {
  availability_zones = ["ap-northeast-1c"]
  name = "autoscalinggroup-test-v1"
  max_size = 0
  min_size = 0
  health_check_grace_period = 300
  health_check_type = "ELB"
  desired_capacity = 0
  force_delete = true
  launch_configuration = "${aws_launch_configuration.launchconfig_test_v1.id}"
  vpc_zone_identifier = ["${var.subnets.asgtest}""]
  load_balancers = ["${aws_elb.asgtest.name}"]
  tag = {
    key = "Name"
    value = "app-asg"
    propagate_at_launch = true
  }
  tag = {
    key = "SERVER"
    value = "APP"
    propagate_at_launch = true
  }
}
新しい設定
# 新しいLC
resource "aws_launch_configuration" "launchconfig_test_v2" {
  name = "launchconfig-test-v2"
  image_id = "${var.amis.api}"
  key_name = "${var.aws.key_name}"
  instance_type = "t2.micro"
  security_groups = ["${var.security_groups.asgtest}"]
  iam_instance_profile = "asgtest"
  associate_public_ip_address = 0
  user_data = "${file("user_data/app_userdata_v2.sh")}"
}
# 新しいASG
resource "aws_autoscaling_group" "autoscalinggroup_test_v2" {
  availability_zones = ["ap-northeast-1c"]
  name = "autoscalinggroup-test-v2"
  max_size = 4
  min_size = 2
  health_check_grace_period = 300
  health_check_type = "ELB"
  desired_capacity = 2
  force_delete = true
  launch_configuration = "${aws_launch_configuration.launchconfig_test_v2.id}"
  vpc_zone_identifier = ["${var.subnets.asgtest}""]
  load_balancers = ["${aws_elb.asgtest.name}"]
  tag = {
    key = "Name"
    value = "app-asg"
    propagate_at_launch = true
  }
  tag = {
    key = "SERVER"
    value = "APP"
    propagate_at_launch = true
  }
}

で、

この人は何故ここまで頑張ってTerraformを使う必要があるのだろうか、、、っていう部分は聞かないでください!
でもやってて開発者の人にもサーバ構成を共有するとか、インスタンス作成部分とかは作業してこっちでもプルリクエストベースでのコードレビュー(構成レビュー)させてもらえるのは非常にいいと思ってます。


そして、バージョン0.6以降で上手く使えるようになることを祈っていますね。。。


でも ↑ この時よりは状況良くなっていると思います!貢献していきたい。

テラフォーマーズ 13 (ヤングジャンプコミックス)

テラフォーマーズ 13 (ヤングジャンプコミックス)

じょうじょ

2014年の記事アクセスランキング!

大晦日もおつカレー様です。
2014年によく読まれた記事のランキングを出してみようと思い立ったのであります。


ドゥルルルルルルルルルルル、、、、

ドン!

というわけで、

来年もよろしくおねがいしまーすʕ•̫͡•ʕ*̫͡*ʕ•͓͡•ʔ-̫͡-ʕ•̫͡•ʔ*̫͡*ʔ-̫͡-ʔ


ゆく年くる年 吟醸酒 720ml

ゆく年くる年 吟醸酒 720ml

シェルスクリプトだけでMySQLからMongoDBへの移行しちゃう

このエントリは、MySQL Casual Advent Calendar 23日目のエントリです。

どうもどうも乙カレー様です。桑野です。
お酒が入ってるとわけわかんないことをいうことがおおいんですが(ごめんなさい)
さてブログ書こうと思ってアドベントカレンダーのページ見なおしたらなんか書いてあるんですよね。

MySQLだっつってんだろ。
ということで何書こうかなと思ってたんですが、ネタ記事としてシェルスクリプトだけでMySQLからMongoDBへの移行しちゃうのをやろうかと思います。
誰得なのかということであれば俺得です(∗ᵒ̶̶̷̀ω˂̶́∗)੭₎₎̊₊♡ウケトレィ!


と言うかなんか怒られそう、、、ごめんなさいごめんなさいネタが思いつかなかったんですホントですm(_ _)m

ちゅーわけでテストテーブル作ってみる。

まずは移行元のMySQLにテーブル作ってみましょ。
適当に。

mysql> CREATE DATABASE d1;
mysql> use d1
mysql>  CREATE TABLE t1 (
   id INT PRIMARY KEY AUTO_INCREMENT,
   name VARCHAR(20),
   nosql VARCHAR(30),
   price INT UNSIGNED,
   created_at DATETIME
 );
mysql>  INSERT INTO t1 (name, nosql, price, created_at)
   VALUES ("kuwa_tw", "mongodb", 10, now());
mysql> INSERT INTO t1 (name, nosql, price, created_at)
   VALUES ("oranie", "cassandra", 100, now());
mysql> INSERT INTO t1 (name, nosql, price, created_at)
   VALUES ("kakky_h", "hbase", 1000, now());
mysql> INSERT INTO t1 (name, nosql, price, created_at)
   VALUES ("la_luna_azul", "riak", 1500, now());
mysql> INSERT INTO t1 (name, nosql, price, created_at)
   VALUES ("saeoshi", "voldemote", 2000, now());
 mysql> SELECT * FROM t1;
 +----+--------------+-----------+-------+---------------------+
 | id | name         | nosql     | price | created_at          |
 +----+--------------+-----------+-------+---------------------+
 |  1 | kuwa_tw      | mongodb   |    10 | 2014-12-23 21:14:39 |
 |  2 | oranie       | cassandra |   100 | 2014-12-23 21:14:40 |
 |  3 | kakky_h      | hbase     |  1000 | 2014-12-23 21:14:41 |
 |  4 | la_luna_azul | riak      |  1500 | 2014-12-23 21:14:42 |
 |  5 | saeoshi      | voldemote |  2000 | 2014-12-23 21:14:43 |
 +----+--------------+-----------+-------+---------------------+
 5 rows in set (0.00 sec)

ほいできました。

移行しましょう。

MySQLのデータをCSV出力

シェルスクリプトというか、まずはCSV出力でしましょ。

$ mysql -h localhost -u root -p pass d1 -e "SELECT * FROM t1" | tr "\t" "," >> ./dump.sql

全テーブルやりたかったらforで回したりしたらいいんじゃないですかね!

$ for t in `mysql -h localhost -u root  d1 -e "show tables from mysql;" | awk 'NR!=1{ print $1}'`
do
   mysql -h localhost -u root -p pass d1 -e "SELECT * FROM ${t}" | tr "\t" "," >> ./dump_${t}.sql
done

こんなのが出ました。

 cat dump.csv
 id,name,nosql,price,created_at
 1,kuwa_tw,mongodb,10,2014-12-23 21:14:39
 2,oranie,cassandra,100,2014-12-23 21:14:40
 3,kakky_h,hbase,1000,2014-12-23 21:14:41
 4,la_luna_azul,riak,1500,2014-12-23 21:14:42
 5,saeoshi,voldemote,2000,2014-12-23 21:14:43
CSV出力を修正

これでもうMongoDB食わせられるんですが、DateがStringになっちゃってるので変換してみましょう。
MongoDBのextended json formatのページを参照に修正してみましょう(CSVだけど)

$ awk -F, -v OFS=, 'NR!=1{tmp="ISODate(\""substr($5,1,10)"T"substr($5,12,9)"+0900""\")";$NF="";print $0tmp ; next} NR=1{print $0}' dump.csv  > dump_fix.csv
 id,name,nosql,price,created_at
 1,kuwa_tw,mongodb,10,ISODate("2014-12-23T21:14:39+0900")
 2,oranie,cassandra,100,ISODate("2014-12-23T21:14:40+0900")
 3,kakky_h,hbase,1000,ISODate("2014-12-23T21:14:41+0900")
 4,la_luna_azul,riak,1500,ISODate("2014-12-23T21:14:42+0900")
 5,saeoshi,voldemote,2000,ISODate("2014-12-23T21:14:43+0900")

こうなったら成功です。

MongoDB へのインポート

最後はmongoimportコマンドでMongoDBにいれるだけ!

$ mongoimport --host localhost --port 27018 -d d1 -c t1 --type csv --file dump_fix.csv --headerline --drop
connected to: localhost:27018
2014-12-23T22:34:53.535+0900 dropping: d1.t1
2014-12-23T22:34:53.539+0900 imported 5 objects
  • mongoimportのオプションの意味
    • --host 接続先ホスト
    • --port 接続先ポート
    • -d database
    • -c collection
    • --file 読み込むファイル
    • --type ファイルタイプ
    • --hederline 最初の行をヘッダとして見る(フィールド名になる)
    • --drop インポート前にコレクションをDROPする(若干危険)

入った入った!クララも立った!
、、、と言うことでデータみてみましょう。

$ mongo --host localhost --port 27018
 MongoDB shell version: 2.6.4
 connecting to: localhost:27018/test
 > use d1
 switched to db d1
 > db.t1.find()
 { "_id" : ObjectId("54996816e0035c426fd71b2c"), "id" : 1, "name" : "kuwa_tw", "nosql" : "mongodb", "price" : 10, "created_at" : "2014-12-23T21:14:39+0900" }
 { "_id" : ObjectId("54996816e0035c426fd71b2d"), "id" : 2, "name" : "oranie", "nosql" : "cassandra", "price" : 100, "created_at" : "2014-12-23T21:14:40+0900" }
 { "_id" : ObjectId("54996816e0035c426fd71b2e"), "id" : 3, "name" : "kakky_h", "nosql" : "hbase", "price" : 1000, "created_at" : "2014-12-23T21:14:41+0900" }
 { "_id" : ObjectId("54996816e0035c426fd71b2f"), "id" : 4, "name" : "la_luna_azul", "nosql" : "riak", "price" : 1500, "created_at" : "2014-12-23T21:14:42+0900" }
 { "_id" : ObjectId("54996816e0035c426fd71b30"), "id" : 5, "name" : "saeoshi", "nosql" : "voldemote", "price" : 2000, "created_at" : "2014-12-23T21:14:43+0900" }

どうでしょう。はいっております。これは奇跡。
ということでありまして、MySQLからMongoDBに移行したい、なんていう珍しい方がおりましたら是非こんな感じで試してみてはいかがでしょうか。


ただし責任は取れませんが、、、(怪談的な終わり方)


追記

で、締まったかと思ったんですが、、、すいません、、、上記の方法でもISODateでは入ってませんでした、、、。

変換する場合はmongo shellに入って、

db.t1.find({ },{ "created_at": 1 }).forEach(function(document){

    var newDate = ISODate( document.created_at );

    db.t1.update(
        { _id: document._id },
        { "$set": { "created_at": newDate } }
    );
})

という感じでできると思います、、、シェルスクリプトだけでできてないしなんなのこれ、、、もう、、、。

> db.t1.find()
{ "_id" : ObjectId("54998426e0035c426fd71b7b"), "id" : 1, "name" : "kuwa_tw", "nosql" : "mongodb", "price" : 10, "created_at" : ISODate("2014-12-23T12:14:39Z") }
{ "_id" : ObjectId("54998426e0035c426fd71b7c"), "id" : 2, "name" : "oranie", "nosql" : "cassandra", "price" : 100, "created_at" : ISODate("2014-12-23T21:14:40Z") }
{ "_id" : ObjectId("54998426e0035c426fd71b7d"), "id" : 3, "name" : "kakky_h", "nosql" : "hbase", "price" : 1000, "created_at" : ISODate("2014-12-23T21:14:41Z") }
{ "_id" : ObjectId("54998426e0035c426fd71b7e"), "id" : 4, "name" : "la_luna_azul", "nosql" : "riak", "price" : 1500, "created_at" : ISODate("2014-12-23T21:14:42Z") }
{ "_id" : ObjectId("54998426e0035c426fd71b7f"), "id" : 5, "name" : "saeoshi", "nosql" : "voldemote", "price" : 2000, "created_at" : ISODate("2014-12-23T21:14:43Z") }

というわけで、これでOKですm(_ _)m


エキスパートのためのMySQL[運用+管理]トラブルシューティングガイド

エキスパートのためのMySQL[運用+管理]トラブルシューティングガイド



MongoDBイン・アクション

MongoDBイン・アクション

新しいwiredTigerストレージエンジンの始め方とその他のストレージエンジンについて

どうもどうも乙カレー様です。桑野です。
風邪です:(;゙゚'ω゚'):<寒い


MongoDB Advent Calendar 2014 - Qiitaの19日目です!

MongoDB2.8の目玉機能であるところのプラガブルなストレージエンジン、その中でも先日MongoDB社が買収したwiredTigerについては気になる所なのでとりあえず使い方メモまで書いてみますた。*1

wiredTigerとは

wiredTigerとはWiredTiger社で開発を進めていたデータストアで2.8ではMongoDBのストレージエンジンとして採用される予定だったのですが、そこから一転MongoDB社に買収されるという形になりました。今までのmmapv1(従来)形式のデータストアから置き換えになる方向なのではないかと思われます。ということでちょいとやってみようと。

試してみよう

現在MongoDB2.8のRC3まで出てますが、これであればwiredTigerは使えます。

$ cd /opt
$ wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.8.0-rc3.tgz
$ sudo tar zxvf mongodb-linux-x86_64-2.8.0-rc3.tgz
$ mkdir -p /var/lib/mongodb/mmapv1 /var/lib/mongodb/wt
$ chown -R mongodb. /var/lib/mongodb
YAML形式設定ファイル

そしたら次にMongoDBの設定。まずは普通に起動してみましょう。
YAML形式の設定ファイルが使えるようになったので勉強兼ねてそれで。(今までの設定ファイルも使えるよ)

# mongodb_mmapv1.conf
storage:
   dbPath: "/var/lib/mongodb/mmapv1"
   engine: "mmapv1"
   journal:
      enabled: true
systemLog:
   destination: file
   path: "/var/log/mongodb/mongodb_mmapv1.log"
   logAppend: true
processManagement:
    fork: true

起動

/opt/mongodb-linux-x86_64-2.8.0-rc3/bin/mongod -f /etc/mongodb/mongod-mmapv1.yml


普通のもんごっすわw

wiredTiger 起動用の設定ファイル

次はいよいよwiredTigerです。設定ファイルを書きましょう。

# mongodb_wt.conf
storage:
    dbPath: "/var/lib/mongodb/wt"
    engine: "wiredTiger"
    wiredTiger:
        blockCompressor: "none"
systemLog:
   destination: file
   path: "/var/log/mongodb/mongodb_wt.log"
   logAppend: true
storage:
   journal:
      enabled: true
processManagement:
    fork: true

起動

/opt/mongodb-linux-x86_64-2.8.0-rc3/bin/mongod -f /etc/mongodb/mongod-wt.yml


設定項目も諸所用意されているので主要なオプション紹介します。(最新の状態は公式サイトまでm(_ _)m)

# mongodb_wt.conf
storage:
    dbPath: "/var/lib/mongodb/wt"
    engine: "wiredTiger"
    wiredTiger:
        collectionConfig:
            blockCompressor: "snappy"
        engineConfig:
            cacheSizeGB: 2
            checkpointDelaySecs: 60
            statisticsLogDelaySecs: 5
            journalCompressor: "snappy"
            directoryForIndexes: true
systemLog:
   destination: file
   path: "/var/log/mongodb/mongodb_wt.log"
   logAppend: true
storage:
   journal:
      enabled: true
processManagement:
    fork: true
  • blockCompressor: コレクションデータの圧縮 "none|snappy|zlib"
  • cacheSizeGB: WiredTigerのキャッシュ量。デフォルトは1G or フィジカルメモリの半分
  • checkpointDelaySecs:  チェックポイントの間隔ジャーナル有効にしてないと最大この秒数のデータが失われる可能性がある。デフォルトは60Sec。
  • statisticsLogDelaySecs:  統計ログの出力間隔、デフォルトは0(記録しない)
  • journalCompressor:  ジャーナルファイルの圧縮。 "none|snappy|zlib"
  • directoryForIndexes: indexとcollectionをディレクトリで分けるようにする。デフォルトはfalse(無効)

ほかにどんなストレージエンジンがあるの?

見た感じこんなのがあるっぽい。

devnullストレージエンジン

insertとかしても何も記録されなかった。MySQLでいうBlackhole。
使い道、、、あるかなぁ、、、。

inMemory(inMemoryExperiment)ストレージエンジン

Experimentってあるので実験段階なんだろうけどメモリDBとして使うためのストレージエンジンぽい。Cappedで使っている用途はもはやこれでもいいんじゃないかと思わなくもない。

RocksDB(rocksExperiment)ストレージエンジン

RocksDBをバックエンドに持つストレージエンジン。使う時間なかったのでよくわからんw

今日はこんなところで勘弁してやらぁ(ください)

もうちょいやりたかったんですが、今日が終わりそうなのでとりあえずここまで。。。

( `)3')▃▃▃▅▆▇▉ヴェェェェェェエェエエェェェェェェエェエエェェヴェェェェェェエェエエェェェェェヴェェェェェェエェエエ


MongoDBイン・アクション

MongoDBイン・アクション


モンゴ流 スカルプエッセンス Deeper 60ml

モンゴ流 スカルプエッセンス Deeper 60ml

*1:もうちょいやりたかったんですが、、、

#mysqlcasual MySQL Casual Talks vol.7に行ってガチカジュアルな話してきた

どうもどうも乙カレー様です。桑野です。

MySQL Casual Talks vol.7に言ってまいりました!
思えば長いこと出れておらず久々の出席でしたが、今回はなんといっても @ さんの4.0移設の話が間違いなくNo.1ですね、、、面白い&色々背筋が寒くなる話でしたね、、、4.0なんてどこにあるんでしょうね、え?あm(自主規制)


そして、LTですが初めて MySQL Casual Talks お話することが、、、でき、、、ま、、、し、、、た!
といっても、サイトに名前出てなかったのでなんか嫌な予感はしていたんですが、数に入ってなかったんではないかという疑惑はありつつ行きましたがやっぱり入ってなかった感じがします(;・∀・)


ということで異様なスピードでしゃべることになりましたが、とりあえずNVMFS+Compressionためしてみたというところの途中経過のお話をさせていただきました。
最近だとRDSやらで物理サーバ上でMySQLを使ってない人も多いのかなーと思いつつお話しておりましたがどうなんでしょうね。



@Skypeさらされたり、資料に入れられたりとIT芸人化の激しい昨今。
IT芸人でーすって笑いが取れるのはいいことなのか、、、どうなのか、、、と若干悩ましいところではありますが、モンゴハラスメントとともに強く耐えていきたいと思っています。(Cassandra放棄さんと違ってぼくはモンゴを放棄したわけではございません!)


最後に会場提供のLINEの方々をはじめスタッフのみなさま。
そしてこの方 @ さん、乙でしたー!

#isucon 4 に初参加してラッキーパンチで失格になってきました

なんで勝負!!!って盛り上がっちゃうんでしょうね。
はい、乙カレー様です。くわのです。


ISUCON4に初参戦してきました!
ISUCON毎回みてて面白そうだなーと思っていたんですがなんとなく気が引けたり予定が合わなかったりで出れてなかったのですが、会社でTOTECに参加して6位になったりしてちょっと悔しかったり面白かったりしてきたので今回初参加してきました。
大分記憶が薄くなってしまったので思い出しつつ書いていきます。


@, @の3人メンバーででてきました。
言語はNode.jsです。

チームでやったこと(覚えてる限り)

とりあえずサーバ環境を見たり、デフォルト状態のRubyのベンチ結果、デフォルトのNode.jsの結果までみて、Nginxのログと、general_log出したりしてクエリ確認してみる。DBはusersとlogin_logしかテーブル無い。

インデックス

login_logに、

  • ip, succeededの複合インデックス
  • user_id, succeeded, idの複合インデックス

を入れてみたタイミングでだいたいMySQLはまあいいんじゃねって感じになった。
ので、あとは様子見つつアプリの確認などしつつmy.cnfやサーバのリソース確認していた。

MySQLバージョンアップ

DBが大したことなかったので5.7にあげてみたけどほぼ意味なかった。

静的ファイル切り出し

Nginx側で静的ファイルの切り出しをして、Nginxで返すように変更。

tmpfs化

MySQLのデータ領域のtmpfs化

OSパラメータ系
  • my.cnf
  • nginx.conf
  • kernelパラメータ

の変更

ハッシュ計算のスキップ

DBにハッシュ値を入れた

セッションのキャッシュ化

memcached導入

この段階の点数

30000超えてる位だったと思う。

ラッキーパンチ

17時半くらいから
memcachedにセッションキャッシュ入れたりしつつ平行して@さんがbenchmakerの最適値を見たりしてたのですが、その中で期せずしてこれに引っかかって不当に高い点になっていたというのがありました。
その時はなんか実行が長いなとは思ってたのですが、元々1分で終わる前提っていう仕様をしらなかったのもあって、そうかーなんかすげーけどとりあえず時間も無いしそれはそれでやってこうってなりまして。その結果5位に入ってしまいました。確か62000くらいだったと思います。

からの失格

それでもジャッジ的に本戦出れる感じだったんですが、ここをみていただけるとわかるように

「もんご博士(RX有〼)」の7チームは、サーバ再起動後に、再起動前と /report の出力内容が変わってしまっていたり、 /report 自体が動作しなかったりすることが確認され、失格といたしました。

「もんご博士(RX有〼)」の7チームは、サーバ再起動後に、再起動前と /report の出力内容が変わってしまっていたり、 /report 自体が動作しなかったりすることが確認され、失格といたしました。

「もんご博士(RX有〼)」の7チームは、サーバ再起動後に、再起動前と /report の出力内容が変わってしまっていたり、 /report 自体が動作しなかったりすることが確認され、失格といたしました。

皆さんわかってますよね。tmpfs入れてちゃんとデータの保存ができるようになってなかったのです、、、かなしい。
そしてラッキーパンチでもくやしい。

benchmaker2での追試

32000でした。これでは本戦出れないですのでまあ良かったかなーって清々しい気分です。いや、嘘です。ちょっとだけくやしい。

教訓

障害対応じゃないんだからもっと攻めるべきだったなーというのは反省しています。
言い訳すると初めての参加だったので自由度が把握できてなかった部分はあるかもしれない。。。(言い訳すんな)

  • 判断は早く、かつ競技の面もあるので大胆さも大事
  • 役割わけるのもあるだけど全員コードを最初に読み込んでおく事
  • レギュレーションは読み込んでチームメンバーで共有しておく <- イマココ

終わってみて

集中して疲れたけど楽しいいいいいいいいいいいいいいいいいいいいいいいいいいいん!って感じだった。
実際参加してみてから皆さんのブログを読ませていただいたりして大変刺激になりました。

今回は残念なラッキーパンチだったので次回はカッチリ本戦行ったるマン。

お疲れ様でした

ご迷惑おかけした @さんはじめ運営の方々本当にお疲れ様でした!
楽しいISUCONありがとうございます!
本選出場者の方々も頑張ってください!

にしても

ばばさんにも言われたけどここはネタ的にもワンチャンMongoDBだったよなー。って思わなくもないですw


ではではー三(卍 〓ω〓))卍