2014年3月17日月曜日

Bitbucketを使ったリモートリポジトリによるソース同期の運用メモ

いままでローカルでソース管理してたけどいい加減Gitに以降したかったので無料でプライベートリポジトリ作り放題なBitbucketを使いました。

リモートリポジトリだけだと心許ないので、ローカルのファイルサーバにも定期的にバックアップをとっています。


Web01、Web02、WebTest(開発機)といった冗長構成でいくつかのWebサービスを運用しています。
Webサーバの前にはL7スイッチ、さらのその前にはL4スイッチがあります。
Webサーバの後ろにはいくつかのDBサーバ群があります。

L7スイッチを噛ませると運用がすごく楽になるのでオススメです。
個人的にVarnishが好みです。そのままキャッシュサーバにもなるし、C言語ライクな設定ファイルが分かりやすいです。

WebTestはクライアントには公開されませんが、基本的にはWebサーバ群と同じ構成になっているのでWebサーバ障害発生時には公開サーバになります。


・開発からコミットまで

WebTestで色々開発、テストを行います。

IDEはWindowsのNetbeansを使っています。

WebTestにはSambaを立たせており、NetBeansから直接ファイルをいじっています。

ソースを編集したらコミット、Bitbucketのリモートリポジトリにプッシュ、

Web01、Web02からフェッチで完了。

ソースが同期されるまでの微妙な時間差はL7スイッチで適当に切り替えつつ。といった感じです。









2014年3月15日土曜日

MySQL5.7.2 Multi-source Replicationのバグ

負荷分散ではなく、複数のDBサーバの非同期レプリケーションをバックアップとして運用するテストをしていました。http://www.mysqlperformanceblog.com/2013/10/02/mysql-5-7-multi-source-replication/

が、

レプリケーション側(MySQL 5.7 Multi-source Replication)のユーザ権限が付与出来ませんでした。
なにをやってもperformance_schemaにテーブル作成ができないのです。

かなりハマったのですが、結局MySQLフォーラムにバグ報告がされていました。
MySQL6.0から修正されるようです。

labsなので文句言えませんが、意外な盲点でした。

仕方なくMySQL5.7.2でmysqld_multiで複数のDBサーバのレプリケーション構成にして同じ様な構成をとりましたが、マルチソースレプリケーションでスマートに行きたかったところです。




2014年3月11日火曜日

[MySQL on ZFS]CentOS6.5にZFSプールを作ってZFSファイルシステムにMySQL5.7のデータをぶっこんだ話

時間を見つけてはちょくちょく作業してLVSとvarnishでL4+L7な冗長ロードバランサ構成を組みました。

Webサーバは複数構成で冗長化しているのですが、DBサーバはサービス毎に物理的にマスターサーバを一台ずつ設置しています。


当然LVSと組み合わせて冗長化したいところですが、サーバを置く場所が無いのと資金がありません。
仕方ないのでデータのリアルタイムバックアップのみ実現させます。

(KeepAlivedを使ったMySQLの高可用性のあるサーバ構築方法は下記のサイトが大変参考になります)
http://dev.tapweb.co.jp/2011/01/325


まず、適当にサーバを一台作ってMySQL5.7を導入し、マルチソースレプリケーション機能で、各マスターDBサーバのレプリケーションサーバとします。

このレプリケーションにはクライアントから一切クエリが飛んできません。
単純に、マスターDBサーバのバックアップのみに使用します。
機能を限定することでITXベアボーンで十分実現可能です。
MySQL5.7からのマルチソースレプリケーション機能により複数DBサーバのレプリケーションになれます。


今回は、以前NAS用としてZFSで組んだファイルサーバがあったのでそれを利用しました。
ZFSの耐久性は魅力的なのでMySQL5.7のdatadirをZFSのファイルシステム上に設定します。


ここで問題なのが、innodbは非同期IOをサポートしますが、ZFS上では使えません。
innodb_use_native_aio=0のように設定すれば旧来のIOを使うのでZFSでも動作します。

しかし、MySQLをインストールするときにmy.cnfを読んでくれないのでインストールに失敗します。
そんな時は、

mysql_install_db --no-defaults --force --innodb_use_native_aio=0 --datadir=/zfs/mysql

のようなコマンドでデータベースを初期化します。


ZFS上にMySQLを配置するのって意外と需要ないのかもしれません。

解決を模索すること数時間、結構ハマってしまいました。





2014年2月3日月曜日

InnoDB FTSでタグとかスペース区切りでID等の格納しているテーブルの検索が遅い件

よくユーザ参加型サービスを構築するとき、タグやカテゴリとか多用するのですが、大抵コロン区切りでIDをvarcharなりtextなりに格納しています。

検索はFIND_IN_SETで行いますがMySQL5.6のInnoDBではFIND_IN_SETはインデックスを使用できません。文字列型で入れてるので当たり前ですが、LIKEよりかはずっと使いやすく多用しています。


数万件程度のテーブルならそこまで問題にならないことも多いですが、10万件にもなってくるとインデックスが使用出来ない為遅さが目立ちます。



そこでInnoDB FTSでスペース区切りでIDを格納し、Full Text Searchをかけるよう試してみたら単体ではぼちぼち早い、といってもFIND_IN_SETよりはマシ程度なのですが、他のフィールドと合わせてWHERE検索するとfilesortが発生し遅くなります。


なぜfilesortが発生するかというとFull Text Searchではインデックスがその一つしか使用出来ないからです。

Full Text Search→他のWHERE句の検索のためにfilesortということになります。さらにORDERが入ってくると目も当てられません。


filesortでは十分なメモリを積んでいれば問題にならないこともありますが、大抵の場合ファイルIOが発生します。速度をそんなに必要としないシステムでもfilesortがあるとIO負荷が高まり、ローカルのSSDにmysqlバイナリを入れている場合SSDの寿命が短くなり、ネットワーク上のCIFだと帯域を消費します。

さらにFull Text Searchはインデックス作成に時間がかかり、ibdataが肥大化するというデメリットもあります。


InnoDB FTSは使いどころによってはかなり強力ですが、このような用途には向いていないようです。

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()していくのが無難でしょう。