2013年11月18日月曜日

mroongaが割りとクラッシュしやすい件

MySQLの全文検索エンジンにmroongaを使用して数ヶ月サービス運用をしていましたが、

ちょくちょくmroongaがUPDATEロックをやってしまいコネクションが切れずMySQLが落ちる事があります。

復帰させるにはmroongaのロック解除を試しますが、うまく行った事がありません。

仕方ないのでテーブルを丸ごと作りなおすことになります。


その間、DBをクラスタ化してないとサービスが停止します。

原因がはっきりしていれば幾らでも対応できるのですが、ある種のテキストをmroongaがインデックスすると落ちるという程度しかわかっていません。

いつ落ちるか分からないでビクビクしながらサービス運用するのはとても耐えられないので最近はMySQL5.6.4から正式に標準対応したInnoDB FTSを使っています。

PHPでMecabで分かち書きする手間がありますが、特に難しいことでもなく、速度も速いので十分です。

なんといってもMySQL標準で滅多な事がない限りクラッシュしないので安心です。

mroonga(groonga)はプロジェクトポリシーも機能も速度も気に入ってるのですが、個人的にイマイチ実運用をするのは怖いです。


2013年9月6日金曜日

MySQLで遅いRANDを高速に【お手軽版】

MySQLのRAND遅くて困ること多いですよね。

プログラマになりたての頃は常に速いRANDの方法を考えてました。

最近になってやっと常套句が見つかったので紹介します。

SELECT id
  FROM random AS r1 JOIN
       (SELECT (RAND() *
                     (SELECT MAX(id)
                        FROM random)) AS id_)
        AS r2
 WHERE r1.id >= r2.id_
 ORDER BY r1.id ASC
 LIMIT 1

受け売りなんですが、このSQLを見た時は感動しました。
AUTO_INCREMENTを使用しているテーブルならそのまま使えるでしょう。

物にもよりますが、 WHERE r1.id >= r2.id_ の後に評価式を加えて使います。
ブログサイトとかのランダム記事紹介にいいですね。

私の環境では40,000件のレコードからこのクエリでランダムにレコードを抽出すると1msかかりませんでした。
LIMITを変更してももちろん使えます。


2013年9月3日火曜日

AndroidのArrayAdapterでNoSuchMethodError

ArrayAdapterに対してAPIレベル11未満でaddAll()を行った場合発生します。
単純に11未満ではaddAll()が未実装な為です。

適当にArrayAdapterを継承してクラスを作成している場合、addAll系をすべてオーバライドしてループでadd()していくのが無難でしょう。

2013年8月31日土曜日

AndroidのParcelableでwriteToParcel ぬるぽ

簡単な話Parcelableインターフェースを持つクラスのメンバにIntgerは使うなってことです。

ちゃんとキャストするか面倒ならintにしましょう。Null Pointer Exceptionが発生します。

onPauseでBundleにParcelableを保存するときwriteIntを使いますが、Intgerに値を設定しないまま保存しようとするとNullを保存使用をします。

PHPばっかり書いてるとこういう基本的な事を忘れてしまう。

Parcelable実装面倒くさいんだけどなにかいいラッパーライブラリ無いだろうか。

FuelPHPでSessionがCookieに保存できなかった話

FuelPHPをようやく使いこなせてきたところでSessionのset_flashとかを使ってValidationエラーの表示をやろうと思ったらCookieに保存すらされていない現象が起きました。

結果からいうとFuelPHPはなにも悪くなく、リバースプロキシのサーバ時刻がGMTになってたのが原因でした。

同じサーバでバーチャールホストでFuelPHPを複数動かしていたのですが、一方ではSessionが使え、一方ではSessionが使えない不思議な現象で特定まで時間がかかりました。

 

FuelPHPのSessionは賢く、有効期限やらなんやら全部やってくれます。

なぜ同じサーバなのにSessionが動いたり(動いているように見えたり)、動かなかったりしたのかというと、

Sessionが動いてる方ではユーザ認証を使っていたためSessionの有効期限を大幅に伸ばしており、GMT-JSTの時刻差を超えて運用していたのでSession使えていました。

もう一方ではFuelPHP標準のSession有効期限を使っていたため、GMT-JSTの時刻差によって常にSession切れになっていたのです。

 

さらに問題だったのがFuelPHPを動かしているサーバ自体はJSTに設定してあり問題なかったのですが、リバースプロキシとしてVarnishサーバをかませており、そのVarnishサーバの時間がGMTだったことです。

ChromeでCookieを見ていた時、たまたまHTTP Headerを見て気がついたからよかったものの、随分初歩的なミスを犯してしまいました。

普段サーバを立てる時はntpdを一番最初に入れているのにVarnishサーバだけ入ってなかった…

 

mroonga(groonga)+Mecabでtoo long sentence

php5.3 + mysql5.6 + mroongaで数万文字になるテキストにFullTextインデックスを貼って、phpからデータを流しているとMySQLがLost Connectionを吐きデータベースがクラッシュしたように停止することがあります。

mroongaのインデックスが壊れるのでテーブルの再作成が必要になるほどです。

いろいろ原因を考えてmax_allowed_packetを変えたり、timeoutを調整したりしましたが、実際の原因はMecabにありました。

私が作成していたテキストデータは改行コードをPHP上で"\n"としており、問題ないと思っていたのですが、どうもmroongaがMecabで形態素解析するときにそのまま\nという文字として読み込んでいるようでした。

Mecabは改行コードで文章の終わりを見ているようで、数十万文字の文章に改行コードが入っていないとなると文章長すぎ!処理しない!となるようです。

MySQL+mroongaでFullTextを扱わないデータなら\nで問題ないのですが、Mecabはうまく認識してくれないということでPHP_EOLを使用したところちゃんと改行と認識してくれました。

PHP_EOLは環境依存なので使っていなかったのですが、まぁmroongaインデックス用のfieldなのでよしとします。

ハマリにハマって4時間浪費。

レンタルサーバか自社サーバどちらを使うのか

社長にレンタルサーバを使わない理由を聞かれたのでまとめます。

別に嫌いだから使わない訳じゃなくて必要性に合わせて使うことがないだけなのですが。

ここでは個人的なレンタルサーバのメリット、デメリットを書いていきます。

超小規模個人IT屋の極々個人的な意見で、実際に運用するWebサービスによってほとんどケース・バイ・ケースなので悪しからず。

 

レンタルサーバのメリット

レンタルサーバは比較的低負荷なサービスに用いることが多いと思います。

・Wordpress等のブログエンジンを使ったオフィシャルブログ(月間100万PV程度)

・画像、動画等のコンテンツサーバ

・feedクローラプログラム

など、ほとんどサーバスペックを必要としないサービスであれば月額980円程度のVPSレンタルサーバでも十分実用可能です。

2chまとめサイト等最近増えていますが、ああいう用途にも良さそうです。月間1億PVとかになるとスタンドアロンじゃ無理ですが。

 

・初期コストが安い

小規模なシステムなら月額980円程度のVPSで十分です。

サーバを買う初期費用もなく、ネットワーク回線もあり、電気代も月額料金に含まれます。

 

・耐障害性が高い

レンタルサーバではサーバスペックに目が行きがちですが、ネットワーク帯域を別回線として確保できるのがかなり大きです。

自社サーバと合わせて死活監視にも使えますし、自社サーバ障害時はレンタルサーバでホットスタンバイしておけばサービス稼働率を高く保てます。

レンタルサーバプロバイダによってはデータの耐障害性も自社サーバよりよっぽど高いものも多いでしょう。

スタンドアロンでありながらVPSならハードが壊れても問題なくサービスは継続します。

 

・デメリットが減ってきている

最近ではVPSサーバの台頭により、サーバのOSまるごといじれるレンタルサーバサービスが増えています。

以前はPHPのバージョンが古かったりデータベースはMySQLのみでデータベース数が限られているということもありましたが、その心配もなくなり様々な用途に使用できます。

 

レンタルサーバのデメリット

これも運用するサービスによりことなりますが、共通して言えるのがWANだと言うことです。開発時に割りと手間をとることが多くなります。セキュリティについてもLANより強固にしなければなりません。

 

・サーバが手元に無い

サーバが手元にないとなにかと不便で、レンタルサーバ上のOSのを入れかえようと思ったらデータをすべてネットワーク越しにバックアップして、OSのISOをVPSに送ってtelnetでインストールして…と気軽にいじくるには少々時間がかかります。

開発時にはFTPかsambaを使えればソース反映はなにかと便利ですが(EclipseかNetBeansを使っているので)、ネットワーク帯域やセキュリティの問題が出てきます。しかしこの辺はgitなりクラウドサービスを使えばある程度はカバーできますね。

 

・開発時に不便

開発はローカルでやってしまえばいいと言えばそれまでですが、実環境で動かしてみないとわからないことも多いわけで、自社サーバと同等の開発環境になるかと言えばそうではないと思います。

レンタルサーバへは常にWAN越しになり、SSH、FTP等で常々つなぐことになります。IDEを使っているとFTPクライアントを入れたり、セキュリティの為ハッシュを生成したりキーを変えたりとLANよりは、遥かに手間が増えます。

一度、レンタルサーバに合わせた開発環境を構築していまえば以後は楽になると思いますが、手間です。

 

・なんといってもサーバスペック

メリットで上げた程度のサービスならCPU2コア、メモリ512MB、ディスク10GBもあれば十分ですが、少し複雑なデータベース構成にしようと思ったら一気にスペックが足りなくなります。

現在、私が運用しているシステムはデータ件数1000万件以上、MySQLバイナリで40GB以上、CPUは8コア3Ghzでメモリ24GBのシステムがあります。ほとんどの時間帯すべてでこれらのリソースを常に使用しています。

これをレンタルサーバで行おうと思ったら初期費用8万円、月額9000円程度になります。上記システムの動かしているサーバは自作で、5万もかかっていません。電気代は月3000~6000円といったところでしょうか。

どうしても高負荷になるサービスをレンタルサーバで行おうと思ったら管理費が高くなるのです。

レンタルサーバにはネットワーク帯域と耐障害性という強みを持っていますが、正しいバックアップ運用とシステムとネットワークの多重化をしていれば運用上問題ない耐障害性は作れます。

 

・結局自社サーバで事足りてしまう。

自社サーバが複数台あればバーチャルホストで低負荷なサービスは量産できますし、運用コストも安く開発もやりやすいです。

課金システムを含むサービスや個人情報を含むサービス等、絶対にデータ紛失を行なっては行けない場合はネットワーク多重化、UPSの導入等考えるとレンタルサーバを複数台借りて運用した方が安上がりになるでしょう。

 

 

以上の事で私がレンタルサーバを使う機会が少いです。(他にもメリットデメリットあった気がするけど思い出せない)

もちろん必要性と開発、運用コストに合わせて今後レンタルサーバなりAmazon EC2なりGoogle App Engineなり使うこともあるとおもいます。

現時点では自社サーバで開発、運用するのが一番楽です。