またまたmongo-php-driver問題
前回の困ったちゃんをまた直しました・・・
また一言!
mongo-php-driver はマトモに動かん!!
いつの間にかmasterブランチにメモリリークが組み込まれてる!!
→ v1.2ブランチは無事
なんだってこんなに頻繁にメモリリークをぶっ込むんだろうか?
ったく・・・
まあそれは置いといて、今回は障害発生時のコネクションの話。
唐突に!
MongoDBはC-Pシステムである。
CAP定理
- 一貫性(Consistency)
- 可用性(Availability)
- 分割耐性(Partition Tolerance)
MongoDBは、一貫性を諦めておらず可用性(availability)を妥協している。
これは書き込みは常にマスターが行う事でこれを実現している。
プライマリDOWNの際は自動的にセカンダリが昇格するものの
ある程度のタイムラグが発生しその間書き込みが不可能となる。
よって、、
MongoDBを利用するアプリケーションはあらかじめ
『障害時には【ある程度】接続できない時間がある』
事を考慮して作らなければならない。
そうは言っても
ある程度!ってどの程度!?
1. 5秒?
2. 30秒?
3. 1分?
4. 3分?
5. 10分?
大体、どの程度のDOWNを見込んだら良いのか解らなければ、アプリも書けないよ!!
というのが今回のお題です。
皆さんどの位まで許せますか?
僕は2.かギリギリ3.なんですよね
お題にしている以上、想像つくとは思いますが・・・思ったより長いのです。
mongo-php-driverでは、、
3.と4.の間です!
mongo-php-driver with replica-set
mongo-php-driverは60秒毎にreplica-setの構成チェック(rs_ping)が走っている。
※赤字はmongod側の挙動
プライマリDOWN時の挙動
1. recplica-setのプライマリDWON
recplica-setは一時的にプライマリ無しの状態になる。
2. (リクエストを送るプライマリが無い為) 書き込みリクエストが失敗し始める。
Error: couldn't determine master
次のrs_pingまで続く
3. revote後、新しいプライマリが決定される
4. 60秒毎のrs_pingが行われ新しいプライマリが判明する。
5. 100秒前後で復旧
じゃあどうするのか?
解は2つあります。
mongos導入
多数のhttpdプロセスが個々にreplica-setの変更に追従するのは時間もコストもかかるので
思い切って(shardcollectionはせずに)sharding構成にしてmongosを導入。
システム構成的にも綺麗になってお勧めです。
メリット:
障害周りの複雑な処理をmongosに丸投げして
mongo-php-drikverはローカルホストのmongosと安定したコネクションを維持できます。
mongodへのコネクション数も半分以下に減らせます。
buggy! なmongo-php-driverに負担を掛けずに済む!!
デメリット:
mongod(config server)を立てる必要がある。
運用が面倒くさい・・・
mongosはmongosでちょっと問題がある。
mongo-php-driverを直す
でも運用が面倒な人(自分)の為に直しました。
リクエスト失敗時に60秒待たずにrs_pingを投げてしまう。
今回は5秒毎に投げる事にしました。
pull-request
これでMongoDBの構成変更に5〜10秒程度で追従できます。
無事取り込まれると良いのだけど・・・
それまでは、こちらでメンテしてます。
github