C++でMeCabを使ってみる。
http://mecab.googlecode.com/svn/trunk/mecab/doc/libmecab.html のサンプルを参考にした。
ページの下にコンパイル方法が書いてある。
#include <iostream> #include <mecab.h> int main(int argc, char **argv){ char input[1024] = "太郎は次郎が持っている本を花子に渡した。"; MeCab::Tagger *tagger = MeCab::createTagger(""); const char *result = tagger->parse(input); std::cout << "INPUT: " << input << std::endl; std::cout << "RESULT: " << result << std::endl; return 0; }
コンパイルは「gcc -I/usr/local/include test.cpp -L/usr/local/lib -lmecab」で通した。
コンパイラのオプションの意味は下記。
-llibrary
名前が library であるライブラリをリンク時に使用します。リ ンカは、標準のライブラリ用ディレクトリのリスト中から、実際のファイル名
が ‘liblibrary.a’ であるファイルを検索します。リンカはこのファイルを、 フ
ァイル名で直接指定した場合と同様に使用します。検索するディレクトリには、いくつかの標準システムディレクトリと、‘-L’ によ
って指定したディレクトリが含まれます。通常、この方法で発見されるファイルはライブラリファイル、つまりいくつか の
オ ブジェクトファイルをメンバとして含むアーカイブファイルです。リンカは、
アーカイブファイルの中を検索して、参照されているが定義されていないシン ボ
ル を定義しているメンバを探し出します。しかし、もしリンカがライブラリでな
く通常のオブジェクトファイルを発見した場合は、そのオブジェクトファイル を
通常の方法でリンクします。‘-l’ オプションを使用する場合とファイル名を直接
指定する場合の違いは、‘-l’ の場合が library を ‘lib’ と ‘.a’ で囲み、いく
つものディレクトリを検索することだけです。
-Ldir ディレクトリdir を ‘-l’ による検索が行なわれるディレクトリのリストに加 え
ます。
-I- ‘-I-’ オプション指定前に ‘-I’ オプションによって指定された全てのディレ ク
ト リは、‘#include "file"’ の形式によってのみ検索されます。これらのディレ
クトリは ‘#include’ によっては検索されません。 ‘ -I-’ オプション指定後に ‘-I’ で指定したディレクトリは、 全 て の ‘#in-
clude’ 命令によって検索されます。(通常は 全ての ‘-I’ で指定されたディレク
トリはこの方法で検索されます。)これに加えて ‘-I-’ オプションは、カレントディレクトリ (現在の入力ファイル
が存在するディレクトリ) が ‘#include "file"’ に対する最初の検索対象となる
ことを抑制します。‘-I-’ によるこの効果を上書きする方法はありません。‘-I.’
を 指定することによって、コンパイラが起動されたディレクトリが検索されるこ
とを指定することは可能です。これはプリプロセッサが行なうデフォルトの動 作
とは異なりますが、たいていはこれで十分です。‘-I-’ は、ヘッダファイルの検索に標準のシステムディレクトリを使うことを抑
制するわけではありません。従って、‘-I-’ と ‘-nostdinc’ は独立です
mecabのインストール
昨年末にバージョンがあがっていたので再度インストールしなおした。
makeの時点でエラーが出たが、コンパイラのヴァージョンを変更して無事インストールできた。
備忘録。
##以下のようなエラーが出るときは。。
/bin/sh ../libtool --tag=CXX --mode=link g++ -O3 -Wall -o mecab mecab.o libmecab.la -lpthread -lpthread -lstdc++
libtool: link: g++ -O3 -Wall -o .libs/mecab mecab.o ./.libs/libmecab.so -lpthread -lstdc++
./.libs/libmecab.so: undefined reference to `__sync_val_compare_and_swap_4'##コンパイラをg++44に変更して事なきを得た。
./configure --enable-utf8-only CXX='g++44'
ldconfigを忘れずに。
iptables
さくらVPSのプランを乗り換えたので、これを機にiptablesの設定もやっておくかと思い調べた。
だが結局自分のケースではSSHのポート変更とhosts.allowやhosts.denyの設定で事足りることが分かった。
備忘録的に書いておく。
以下メモ
>>概念
・テーブル
filter, nat, mangleの3つがある。
それぞれパケットフィルタリング、アドレス変換パケット処理に対応
画像の各フローにリストしたテーブルが、各フローで使える・チェイン
組み込みチェインとユーザ定義チェインの2つがある。
画像の各フローに対応した組み込みチェインがある。
・ターゲット
ルールに合致したパケットに行う処理のことをターゲットと呼ぶ。・ルール
パケットの内容との比較条件
- -
>>チェインの作成・削除・変更
iptables -t filter -N MYTEST
iptables -t filter -X MYTEST
iptables -t filter -E MYTEST HOGE
- -
>>チェインのルールの操作
・ポリシーの設定
iptables -P
chainにはINPUT, OUTPUT, FORWARDのみ指定できる。ユーザ定義チェインは指定できない
targetにはACCEPT, DROPのみ
原則ルールの決定です。デフォルトではACCEPTになっていて、何も設定しなければ
全てを通過させるようになっています。・ルールの追加
iptables -A
- -
>>パケットフィルタリング
2つのモデル
1.厳密に必要な通信だけを許可する
2.サーバ内部から外部への通信は全て許可。外部からサーバ内部への通信は
必要なものだけを許可する。
だいたいは2のケースでいいやってなるのかな。個人的な用途のサーバであれば
そんな感じ。
- -
>>実例
# iptables -N MYCHAIN
# iptables -A INPUT -j MYCHAIN
# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
MYCHAIN all -- anywhere anywhereChain FORWARD (policy ACCEPT)
target prot opt source destinationChain OUTPUT (policy ACCEPT)
target prot opt source destinationChain MYCHAIN (1 references)
target prot opt source destination//policyはACCEPTとなっていてユルユルの設定。
//これがモデル1であればDROPにしてstrictな設定にする。# iptables -A MYCHAIN -s 123.123.123.123 -p tcp --dport 22 -j ACCEPT
# iptables -A MYCHAIN -s 0.0.0.0/0 -p tcp --dport 22 -j DROP
//指定したIPからのSSHアクセスをACCEPT
//全てのIPからのSSHアクセスをDROP# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
MYCHAIN all -- anywhere anywhereChain FORWARD (policy ACCEPT)
target prot opt source destinationChain OUTPUT (policy ACCEPT)
target prot opt source destinationChain MYCHAIN (1 references)
target prot opt source destination
ACCEPT tcp -- 123.123.123.123 anywhere tcp dpt:22
DROP tcp -- anywhere anywhere tcp dpt:22
MeCabのソースを読んでみる。
C++とかCの勉強は中途半端にやってはやめを繰り返していた。
やっぱり仕事でがしがし使わないのでなかなかモチベーションを維持できないのが大きい。
でも幅を広げたいのでちょっと頑張ってみることにした。会社で技術発表が2ヶ月おきくらいに
回ってくるのでそれに間に合うように形態素解析の薀蓄をコードを読んで、C++がある程度
書けるようになってプレゼンできればなと思う。
いきなりコードを読むのではなく下調べとして自然言語処理というジャンルにおける形態素解析の
位置づけみたいなのをざっくりとまとめた。それが以下。
形態素解析は4つの解析ステップの内の一つということになる。「自然言語処理の基礎」(コロナ社)を読んだ限りでは、
形態素解析の役割は大きくわけて3つでマインドマップに書いた通り、「単語分割」・「品詞付与」・「原型の復元」となる。
MeCabのソースを見るとクラス名も役割に応じた名前になっていたりするのでなんとなくイメージしやすい印象があった。
アルゴリズムとかも鼻血が出るほど難しいというわけでもなさそうなので、なんとかなるかな。
2ヶ月かけてC++のお勉強とともにやっていきます。毎日1.5時間を当てられたらスゴイなー。
頑張れ自分。
さくらVPSにSubversionとTracをインストール。
自宅サーバではバックアップはかなり適当な感じだったので、しこしこ書き溜めているソースの管理はさくらのVPSに移した。月額980円の年間1万ちょっとで安心が買えるのはとても安いと思った。メモリが512Mのプランなので他にはネームサーバとかを移したぐらい。
以下はコマンドの発行手順。自宅サーバから手軽にチェックアウトしたいというような場合は秘密鍵をほげほげして.bashrcに「export SVN_SSH ...」を記述してみたいな感じの作業があった。備忘録。
git、使えるようにならないといけないな。めんどくせ。
tracのインストール方法 useradd taro groupadd svn ##wget http://pypi.python.org/packages/2.4/s/setuptools/setuptools-0.6c11-py2.4.egg ##sh setuptools-0.6c11-py2.4.egg yum -y install httpd-devel yum -y install mod_python yum -y install python-setuptools easy_install --always-unzip Genshi yum -y install mod_dav_svn wget http://www.i-act.co.jp/project/products/downloads/Trac-0.11.7.ja1.zip unzip Trac-0.11.7.ja1.zip cd Trac-0.11.7.ja1 python ./setup.py install mkdir /home/svn svnadmin create /home/svn/repos chown -R root.svn /home/svn chmod -R 775 /home/svn svnグループに参加させる usermod -G taro,svn taro usermod -G apache,svn apache su - taro cd ~ mkdir tmp echo "TEST" > tmp/test.html svn import tmp file:///home/svn/repos -m "import" exit cd /etc/httpd/conf.d mv proxy_ajp.conf proxy_ajp.conf.org mv python.conf python.conf.org mv subversion.conf subversion.conf.org mv welcome.conf welcome.conf.org htpasswd -c /var/www/.htpasswd taro emacs /etc/httpd/conf.d/trac.conf ################################################### LoadModule python_module modules/mod_python.so <Location /trac> SetHandler mod_python PythonHandler trac.web.modpython_frontend PythonOption TracEnvParentDir /home/trac SetEnv PYTHON_EGG_CACHE /home/trac/.egg-cache </Location> <LocationMatch "/[[:alnum:]]+/login"> AuthType Basic AuthName "trac" AuthUserFile /var/www/.htpasswd Require valid-user </LocationMatch> ################################################### mkdir /home/trac chown -R apache.apache /home/trac su -s /bin/bash - apache cd /home/trac trac-admin /home/trac/test initenv >>Project Name [My Project]> TEST >>Repository type [svn]> >>Path to repository [/path/to/repos]> /home/svn/repos ブラウザから http://yourdoman/trac を確認 <管理画面を見れるようにする> cd /home/trac/test trac-admin ./ permission add anonymous TRAC_ADMIN logo_bannerを /home/trac/test/htdocs以下にコピペ exit
MySQL Spiderエンジンを使ってみた。〜データベースシャーディング(sharding)とは〜
もしかしたら使うかもしれないので調べてみた。
shard
- 日本語に訳すと(ガラスや貝殻の) 「破片」といったような意味
- データベースをshardに分解して複数のサーバに分散して運用するのがDB sharding
- データベースパーティショニングとも言えるのかしら?
- 単一のサーバのDBテーブルを複数のファイルに分割するのをパーティショニングとも呼ぶが、「パーティショニング」という言葉を使ってDB shardingのことを言っているブログ等もちらほら見かけます。
- より突っ込んでみたい人は「shared nothing」でぐぐってネ。
なぜデータベースを分散処理するのか
横軸にはサービス運用開始からの時間経過を設定し、縦軸には「DBの応答時間」、「DBへの問い合わせ数」、「DBサイズ」の各数量をとります。サービスが順調に利用されていっているものとし、「DBサイズ」や「DBへの問い合わせ数」は時間経過とともに線形に増えていきますが、「DBの応答時間」はある時を境に指数的に増えていくことが想定できます。要するにDBのレスポンスは急激に悪化することがあります。原因としては以下が考えられます。
- メモリに乗り切らないデータはディスクを読み込んで探さなければならない。
- ディスクからデータを探すのとメモリからデータを探すのでは速度差に10の5乗〜6乗近くの差が出る(10万倍〜100万倍)
スケールアップ・スケールアウトという枠組みで解決法が考えられますが、今回の主題から言うと次のようになります。
スケールアウト戦略
DB shardingは単一のサーバでの処理能力が著しく落ちない程度にデータの大きさを調節する(データベースサイズをスケールする)ことでDBの性能を最大限に引き出せるようにする手法です。MySQLのSpiderエンジンは手軽にDBを分散処理できるようにしてくれています。
これに対してレプリケーションはDBへの参照問い合わせをスケールしてくれていると言えるでしょう。
Spiderを使った時のイメージ
上記の図はサーバ4台の構成で、黄色のサーバはアプリケーションサーバでDBサーバも兼ねています。が、DBのデータの実体は各オレンジ色のDBサーバに分散されて黄色のサーバはデータは保持していません。
実際に使ってみる前に
- テーブルパーティショニングについて
- MySQL Sandboxについて
テーブルパーティショニング
RANGE分割
下記のようなCREATE文を発行することで通常は一つのMYDファイルに保存されるところをp0.MYD, p1.MYD, p2.MYD, p3.MYDのように4つのファイルに分割してデータを保存することができるようになります。ちなみにこのSQL文だけだと単に同一のサーバにファイル分割しただけとなります。同一のサーバでも異なるHDに分割できるようにすればデータの読み込み速度も上がるのかなと思ったりしますが、単純にファイル分割しただけで何がどう変わるとかまでは調べておりません。。
CREATE TABLE t_range ( name text, hight int, birthday date ) ENGINE=MYISAM PARTITION BY RANGE(hight) ( PARTITION p0 VALUES LESS THAN (150), PARTITION p1 VALUES LESS THAN (170), PARTITION p2 VALUES LESS THAN (180), PARTITION p3 VALUES LESS THAN MAXVALUE )
LIST分割
CREATE TABLE t_list ( name text, hight int, birthday date ) ENGINE=MYISAM PARTITION BY LIST(MONTH(birthday)) ( PARTITION p0 VALUES IN (1, 2, 3), PARTITION p1 VALUES IN (4, 5, 6), PARTITION p2 VALUES IN (7, 8, 9), PARTITION p3 VALUES IN (10, 11, 12) );
HASH分割
CREATE TABLE t_hash ( name text, hight int, birthday date ) ENGINE=MYISAM PARTITION BY HASH(MONTH(birthday)) PARTITIONS 4;
KEY分割
CREATE TABLE t_key ( id int, name text, hight int, birthday date ) ENGINE=MYISAM PARTITION BY KEY(id) PARTITIONS 4;
MySQL Sandboxとは
- 簡単に複数の検証用環境を立ち上げることができます。
- CPANからインストールできる。(http://search.cpan.org/~gmax/MySQL-Sandbox-3.0.17/lib/MySQL/Sandbox.pm)
- Perlerでない場合は
Spiderを実際に使ってみる。
- Spiderエンジンのインストール
- MySQL::Sandboxでの環境構築
- Spiderエンジンのインストール
- Spiderテーブルとリンク先のテーブルを作成
- データ操作してみる
Spiderエンジンのインストール
- https://launchpad.net/spiderformysqlからダウンロード。5.5系はSpiderのソースも組み込まれたMySQLのソースを全コンパイルしてのインストールのみとなる。SpiderのみをPluginで追加できるのは現在は5.1系のみ
- 5.5系は./configureの代わりにcmakeを使うようになった。PREFIXを指定して自分のホームディレクトリにインストール
MySQL::Sandboxでの環境構築
Spiderエンジンのインストール
Spiderテーブルとリンク先のテーブルを作成
mysqlのドキュメントページからダウンロード(http://dev.mysql.com/doc/index-other.html)できるemployeeデータベースを使ってサンプルを作成する。
- spiderノードにはspiderテーブルを作成する
- ./n1 spider_test < table_for_spider_node.sql
CREATE TABLE salaries ( emp_no int(11) NOT NULL, salary int(11) NOT NULL, from_date date NOT NULL, to_date date NOT NULL, PRIMARY KEY (emp_no,from_date), KEY emp_no (emp_no) ) ENGINE=SPIDER DEFAULT CHARSET=utf8 PARTITION BY HASH(emp_no) ( PARTITION p1 COMMENT 'user "msandbox", password "msandbox", host "127.0.0.1", port "13916", table "salaries",', PARTITION p2 COMMENT 'user "msandbox", password "msandbox", host "127.0.0.1", port "13917", table "salaries",', PARTITION p3 COMMENT 'user "msandbox", password "msandbox", host "127.0.0.1", port "13918", table "salaries",' );
- node2〜node4までは通常のテーブルをインストールする
- ./n2 spider_test < table_for_normal_node.sql
CREATE TABLE salaries ( emp_no int(11) NOT NULL, salary int(11) NOT NULL, from_date date NOT NULL, to_date date NOT NULL, PRIMARY KEY (emp_no,from_date), KEY emp_no (emp_no) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
- 先ほどのサンプルのemployeesデータベースを解凍し、salariesテーブルをspiderノードにロードしてきちんと分散処理されているかを確認します。
データ操作してみる
- ./n1 spider_test < load_salaries.dump (topで様子を見ると並列処理している様子がみれて面白いかなと)
$ ./n1 spider_test -e 'select count(*) from salaries';
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
count(*) |
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
2844047 |
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
$ ./use_all -e 'use spider_test; select count(*) from salaries'; # server: 1: count(*) 2844047 # server: 2: count(*) 947747 # server: 3: count(*) 947505 # server: 4: count(*) 948795
- 既存のテーブルをshardingしたいという場合もspiderを使うと簡単に処理できます。
- 先ほどは直接spiderノードにデータをロードしましたが、既存のテーブルにspiderのリンクを貼ってそこからデータを直接引っ張ってくることもできます。下記のようなSQLで一発です。
insert into salaries select * from salaries_datasource
- 集約関数は機能する?
- 単一のサーバにロードされたsalariesテーブルからデータを間引いてサラリーの平均を確認し、spiderで運用しているデータにも同様の操作をしてきちんと数値が一致するかを確認します。
まずは単一のサーバにロードされたsalariesテーブル mysql > desc salaries; +-----------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-----------+---------+------+-----+---------+-------+ | emp_no | int(11) | NO | PRI | NULL | | | salary | int(11) | NO | | NULL | | | from_date | date | NO | PRI | NULL | | | to_date | date | NO | | NULL | | +-----------+---------+------+-----+---------+-------+ 4 rows in set (0.00 sec) mysql > select AVG(salary) from salaries;
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
AVG(salary) |
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
63810.7448 |
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
count(*) |
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
2844047 |
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
count(*) |
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
34 |
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
AVG(salary) |
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
63810.9068 |
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
count(*) |
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
2844013 |
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
次いでspiderテーブル node1 > select AVG(salary) from salaries;
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
AVG(salary) |
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
63810.7448 |
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
count(*) |
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
34 |
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
AVG(salary) |
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
63810.9068 |
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
おわりに
とまあ以上のような感じで検証しました。参考にさせてもらったのは主にhttp://nippondanji.blogspot.com/2010/04/spider.htmlでした。
あと、レプリケーションして使いたいとか、そういうケースも調べてみたのでまた別エントリで書きたいと思います。
自宅サーバ派の自分としては結構使い道があるなと思ったりもしています。