キーバリュー型データストア

いまさら?今から?
とりあえずキーバリュー型データストアという名詞を今知ったばかりなので個人的にファーストインプレッション。

なぜキーバリュー型データストアが必要か

適当にぐぐって2,3個人ブログを読んだだけなんだけど、この辺り明記されてる方の記事に出会えなかったので、もっとぐぐればあるんだろうけど書いてみます。

RDBMSじゃダメなの?

全然OKです。
RDBMS使ってて捌ききれる処理数でコストもそれ程かかっていないのなら問題なしです。
そうじゃなくなってきた色んな意味で限界が来た時にRDBMS以外の使用を考えればいいと思います。

RDBMSじゃダメな理由って何なの?

一言で言うと、
インターネットのおかげでRDBMSでは頭打ちになってしまう程の情報量が集まってしまう場合が出てきたから、です。

↑よりは細かく説明すると

一般的に広く使われているRDBMSというのはOracleだったりMySQLだったりPostgreSQLだったりしますね。
お金が唸ってるPJが信頼性と責任分担を求めて高額なOracle、ってなったり、そうでないPJがライセンスのしばりのきつくないPostgreSQLを選んだり、というのが最初の段階。
使っているうちにユーザ数が拡大したりなんだりで、パフォーマンスの改善を行う必要が出てきます。
その時に考慮される手法をDB寄りで考えると、

  • DBサーバをスケールする
  • DBを早いものに入れ替える

サーバのスケールには単純にスペックの増強/サーバ台数の増強などを行います。
DBの入れ替えは単純に処理速度の速いRDBMSを使用する、という事になりましょう。
開発にはいろんな縛りがあるので、そういう変数を全部ぶっ飛ばしてやれる事をやろうとするなら、
まず1サーバでやっていたならRDBMSを入れ替える。当然サーバをスケール(この場合は複数台)にした場合にそのRDBMSが対応するか、を考慮する必要はありますが、スケールさせた場合にどういう手法で可用性を確保するにしろ今時のRDBMSはそれなりにスケールに対応していますので単純に「処理の早いRDBMS」を選定するとしましょう。

で、元々早いRDBMSを使ってたよ!とか入れ替え済みだよ!ってなったら次にサーバをスケールするわけです。
これもそのRDBMSが元々持っている機能やサードパーティが作った拡張機能なんかで何とかします。
その使い方を調べて構築、設定、はい再起動、できたー!ですね。

そしてここです。
それでも対応できないくらい処理が増加した場合は?
ここで言う「対応できないくらいの処理」というのはWEBサービスを考えると分かりやすいと思います。
Twitterみたいなユーザ数が膨れあがってるけどデータを格納するタイプのサービスですね。
何かもうどうにもならなくなる訳です。
確かにサーバをスケールすれば負荷も分散できて結果的に処理速度も向上します。
しかし、負荷を分散するためにサーバを増やす事によって各DBが連携する負荷が増えている事や、RDBMS自体の処理の限界値は変化しない、という現実が目の前に突きつけられます。
そもそもレコード数の増加し続けるテーブルなどは水平/垂直分割して複数サーバに格納される事になるのでメンテナンスが大変です。

この状態になってもまだ着手していないならできる事はまだあります。
memcacheなどを使用してメモリを有効に利用し、1処理辺りの処理時間を短縮しようという試みです。
コードのリファクタリングを行ってSQL発行回数を減らしたり、使用しているSQLやその結果バッファがRDBMS側のキャッシュに乗るようにしたりなども同じような意味を持ちます。

このように、サービスをスケールして行く事によってユーザ数を捌くという事を続けていくと、コードの改変、運用維持、スケールテストとその実施、NEも鯖缶もPGもSEも全員てんてこ舞い。そしてある日気付くんですね。
「あれ、これいつ終わるの?」
と。


ここで出てくるのがキーバリュー型データストア、って訳です。
つまりここまで来ないならお好きなRDBMSを使っててOKだと思います。

キーバリュー型データストアの実際

GoogleAmazonなどの大規模サイトが以前から使用しているのを気付かずに使用されているかも知れませんが、どうでしょうか使い心地は?
その反応(処理)速度がキーバリュー型データストアの実際です。

キーバリュー型データストアの長所/短所

一言で言うとアプリケーションなので、その他のアプリケーションと同じ特性を持っています。
処理が早いという事は、その速度に比例して「複雑な処理を行っている回数が少ない」という事です。
つまり当然RDBMSに比べると機能が少ないです。

所感

キーバリュー型データストア、使える部分ではがっつり使っちゃっていいと思います。
幸い大手だからこそぶち当たる壁で出てきはじめたものなので、すでに大手で採用されている技術、ともなると使いどころを間違えさえしなければ採用する事自体には特に問題もないでしょう。

2年前くらいにキーバリュー型データストアっぽいもの(当時は名前も知りませんでしたが)の実装を行った事があります。データ保存型のシステムだったのでバックエンドではしっかりRDBMSが黙々と動いてくれていましたが、memcacheとキーバリュー型データストアを足してストア部分をRDBMSに任せたようなそのサーバアプリで、負荷軽減としては恐ろしい程の結果が出ました。
当たり前ですよね、RDBMSが持つ豊富な機能のうち必要な部分のみの実装を行ったのですから。

残念ながらその時の仕事は日の目を見る事はありませんでしたが、そういう意味でもキーバリュー型データストアは面白いなぁと思ったのでした。

ソースから継承図を作成する

無料という事で doxygenGraphviz を使用します。

れしぴ

doxygen でHTMLドキュメントと dot ファイルを生成します。
生成した dot ファイルを Graphviz の dot を使用して図に変換し、HTMLに表示させる、という感じです。
doxygen の設定さえしてしまえば、上記は doxygen が黙々とやってくれます。

Graphviz のインストール

wget http://www.graphviz.org/pub/graphviz/stable/SOURCES/graphviz-2.22.2.tar.gz
tar zxvf graphviz-2.22.2.tar.gz
cd graphviz-2.22.2/
./configure
make
make install

doxygen のインストール

wget ftp://ftp.stack.nl/pub/users/dimitri/doxygen-1.5.8.src.tar.gz
tar zxvf doxygen-1.5.8.src.tar.gz
cd doxygen-1.5.8/
./configure
make
make install

doxygen 設定ファイルの生成

doxygen -g Doxyfile.conf

doxygen 設定ファイルの修正

必須部分だけ記載します

# 生成したhtmlファイルなどの出力先
OUTPUT_DIRECTORY
# 解析するソースが配置されているディレクトリパスを指定
INPUT
# 解析するソースの拡張子を指定
FILE_PATTERNS
# LATEX は必要ない
GENERATE_LATEX
# dot を使う
HAVE_DOT
# dot が画像を生成する際に使用するフォントパスを指定
# デフォルトでは FreeSans になっているので、システムにインストール
# されていない場合はここでパスを指定する
DOT_FONTPATH
# 生成する画像形式。png だとエラーが出てうまくいかなかった。
DOT_IMAGE_FORMAT
# dot がインストールされたパスを指定
# Graphviz をソースから入れたので今回は /usr/local/bin/
DOT_PATH

どうして画像が出ないんだろう?
と思っていたら画像形式(png でエラー)とフォントがないせいでした。
フォントはダウンロードしたソースに入っているので、そのパスを指定してあげればデフォルトのフォントのまま使えます。

コードスニペット

関数名だけで検索するとコードスニペットが出てきて内容を表示してくれるので、いちいち該当するモジュールのソースをダウンロードして展開して検索して、ってしなくていいので便利。
ツリービューも出してくれるし、何かすごいな。

画像も書籍もソースも、ってなってきてgoogleがライブラリみたいになってきてるなぁ。
検索エンジンと蓄積された情報というのは非常に相性がいいと思うけど、検索技術としては対象と扱いが変わるだけであまり変化がないような気がする。
これからどこに向かうんだろう。

msqlコマンドラインツール

mysqlコマンドラインツールで接続できない。

問題

[shell] $ /usr/local/mysql/bin/mysql -u mysql -p
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

原因

起動しているmysqlサーバのソケットに接続できていない。

対応

接続情報が不足しているので、パラメタとして接続情報が記載されているmy.cnfのパスを渡してしまう。

[shell] $ /usr/local/mysql/bin/mysql --defaults-file=/usr/local/mysql/etc/my.cnf -u mysql -p

もしくは接続情報をパラメタで個別に渡す。

[shell] $ /usr/local/mysql/bin/mysql --socket=/usr/local/mysql/data/mysql.sock --port=3770 -u mysql -p

まとめ

コマンドラインツール起動時に渡せるパラメタ。
http://dev.mysql.com/doc/refman/4.1/ja/mysql.html

データベースの削除ができない

データベース再作成の際にdrop databaseで失敗した場合の対応。

問題

drop database時に何らかの事由によって失敗してしまった場合、コマンド(drop database)による削除を受け付けなくなる。

コマンドで削除

管理ユーザでmysqlにログイン

mysql -u root -p

mysqlの管理ユーザでログインする。

DB名確認

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| test_db            |
| mysql              |
+--------------------+
3 rows in set (0.01 sec)

test_dbを削除

mysql> drop database test_db;
ERROR 1010 (HY000): Error dropping database (can't rmdir './test_db/', errno: 17)

エラー。

対応

データベース情報が保存されているディレクトリを丸ごと削除する。

コマンドは使えないのでDBを物理削除

cd /usr/local/mysql/data
rm -rf test_db

確認

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
+--------------------+
2 rows in set (0.01 sec)