小咄:blazeds+amf client+mysqlで実現するkey-value storage

49
小咄:BlazeDS+AMF Client+MySQLで 実現するKey-Value Storage

Upload: moai-kids

Post on 25-May-2015

3.220 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

Page 2: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

HBaseが重い

Page 3: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

事の顛末クローリングしたブログ記事をHBaseに保存してた。

→2009/03ころからデータ参照処理が非常に時間がかかるようになる。(テーブル数:1000弱 データサイズ:5,000万レコード超)→今まで1時間で終わっていた処理が5時間くらいかかるように・・・・・・→キィィィィィィィィィ!!

Page 4: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

元々HBaseって使い辛いよね

✓書き込んだデータがHDFSのノード上に伝播されるまでタイムラグがある。

✓カウント文が無い。(countコマンドはあるが、全レコードをgetしてその件数を数えてる)

✓まだバグが多い。

Page 5: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

では何故HBaseを使っていた?

見栄

Page 6: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

key-value store• 何を期待している?

- 処理パフォーマンス、シンプルさ- keyさえ分かれば値が取得できる- valueに何でも放り込んでおける(スキーマレス)

- スケーラビリティ- keyさえ分かればデータがどこにあっても良い

• 何を期待していない?- 高機能

- たとえばSQLみたいなDSLによる操作- ロールバック機構

Page 7: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

key-value store• とは言えどもこれは有った方が良い

- 処理パフォーマンス - バックアップ機能- 手軽にレプリケーションできる- ある程度の信頼性

- データが高負荷時に突然破損しない程度

- データリスト/keyリストの取得機能- データ件数取得機能

Page 8: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

比較•memcached•Tokyo Cabinet/Tokyo Tyrant•Voldemort•Apache CouchDB•HBase(一応)

Page 9: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

比較(完全に主観)パフォーマンス レプリケーション バックアップ 信頼性

memcached ◎ ?cloneプロジェクトがいくつかある

× ◎

TokyoCabinet/TokyoTyrant ○ ◎ ◎ ○

Voldemort △ ○採用ストレージによる

○採用ストレージによる

CouchDB △ × × △

HBase × ◎ ◎ ×

Page 10: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

TokyoTyrantは悪く無い• スループットもmemcachedの倍遅い程度• レプリケーション機能標準採用• 比較的堅牢、信頼性がある(mixiのログイン機能他多くの高トラフィックシステムに使われている)

• インターフェースmemcached互換

• ただし使い辛い部分も• テーブル単位でデータを保存するには個数分インスタンス立ち上げ

• keyリストは取れるがカウント文的なものは無い

Page 11: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

こんな記事

Page 12: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

Page 13: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

記事要約• スキーマ追加に伴うインデックス追加が大変• CouchDBみたいなスキーマレスな仕組みにしたい。しかしCouchDBは不安定

• MySQLで良いじゃん。• valueはJSONで保存• 実体テーブルと参照用インデックステーブルを分離実データは実体テーブル上にuuid-bodyの対で保存参照テーブルでは実体検索用のカラムを保持

• 負荷減った

Page 14: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

これだ

Page 15: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

構成CREATE TABLE entities ( added_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, id BINARY(16) NOT NULL, updated TIMESTAMP NOT NULL, body MEDIUMBLOB, UNIQUE KEY (id), KEY (updated)) ENGINE=InnoDB;

実体テーブル

参照テーブルCREATE TABLE index_user_id ( user_id BINARY(16) NOT NULL, entity_id BINARY(16) NOT NULL UNIQUE, PRIMARY KEY (user_id, entity_id)) ENGINE=InnoDB;

{ "id": "71f0c4d2291844cca2df6f486e96e37c", "user_id": "f48b0440ca0c4f66991c4d5f6a078eaf", "feed_id": "f48b0440ca0c4f66991c4d5f6a078eaf", "title": "We just launched a new backend system for FriendFeed!", "link": "http://friendfeed.com/e/71f0c4d2-2918-44cc-a2df-6f486e96e37c", "published": 1235697046, "updated": 1235697046,}※bodyの中身(value)はJSONで保存

アプリ

※user_id→entry_id(key)検索用

Page 16: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

データ登録時CREATE TABLE entities ( added_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, id BINARY(16) NOT NULL, updated TIMESTAMP NOT NULL, body MEDIUMBLOB, UNIQUE KEY (id), KEY (updated)) ENGINE=InnoDB;

実体テーブル

参照テーブルCREATE TABLE index_user_id ( user_id BINARY(16) NOT NULL, entity_id BINARY(16) NOT NULL UNIQUE, PRIMARY KEY (user_id, entity_id)) ENGINE=InnoDB;

{ "id": "71f0c4d2291844cca2df6f486e96e37c", "user_id": "f48b0440ca0c4f66991c4d5f6a078eaf", "feed_id": "f48b0440ca0c4f66991c4d5f6a078eaf", "title": "We just launched a new backend system for FriendFeed!", "link": "http://friendfeed.com/e/71f0c4d2-2918-44cc-a2df-6f486e96e37c", "published": 1235697046, "updated": 1235697046,}※bodyの中身(value)はJSONで保存

アプリ

※user_id→entry_id(key)検索用

1.実体を実体テーブルに保存

2.検索用のレコードを参照テーブルに保存

※非同期で登録も可能

Page 17: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

データ参照時CREATE TABLE entities ( added_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, id BINARY(16) NOT NULL, updated TIMESTAMP NOT NULL, body MEDIUMBLOB, UNIQUE KEY (id), KEY (updated)) ENGINE=InnoDB;

実体テーブル

参照テーブルCREATE TABLE index_user_id ( user_id BINARY(16) NOT NULL, entity_id BINARY(16) NOT NULL UNIQUE, PRIMARY KEY (user_id, entity_id)) ENGINE=InnoDB;

{ "id": "71f0c4d2291844cca2df6f486e96e37c", "user_id": "f48b0440ca0c4f66991c4d5f6a078eaf", "feed_id": "f48b0440ca0c4f66991c4d5f6a078eaf", "title": "We just launched a new backend system for FriendFeed!", "link": "http://friendfeed.com/e/71f0c4d2-2918-44cc-a2df-6f486e96e37c", "published": 1235697046, "updated": 1235697046,}※bodyの中身(value)はJSONで保存

アプリ

※user_id→entry_id(key)検索用

1.keyが明示な場合は直接実体テーブルに参照に行く

2.keyが不明な場合、参照テーブルから条件に合致する

key情報を取得する

Page 18: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

FriendFeed版スキーマレスDBの利点

• key-value storeのメリットを享受しながら、MySQLの性能(パフォーマンス、利便性、信頼性)や実績/ノウハウをそのまま使用できる

• 参照テーブルを用意する事で普通のDBと同じような操作が可能になる

• インデックス追加のコストが低い• 検索用の参照テーブルを非同期で作成すれば良い• 要件によっては非同期に更新しても良い。I/O負荷の分散/平板化がしやすい

Page 19: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

データをJSON形式で保存する功罪

• メリット• スキーマレス(何でも放り込める)• 可視性。何か有った時に目で確認→直接編集できる

• 標準フォーマット(RFC4627)• デメリット

• バイナリ形式に比してデータが冗長になる• バイナリを扱うには文字列符号化が必要• BLOBに可変長のデータを放り込むためフラグメントが起こりやすい

• 生理的に嫌

Page 20: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

参照テーブルを非同期で更新することの功罪

• メリット• 更新処理を非同期にすることができる。• インデックスの追加やデータリカバリが容易• スループットの向上。I/O負荷の平板化

• デメリット• 更新したデータが、更新直後に参照できない可能性がある(ACIDモデルの崩壊)

Page 21: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

CAP定理• Consistency(一貫性)、Availability(可用性)、Partition

tolerance(並列性)の3つ全てを同時には満たせない、という定理。http://www.cs.berkeley.edu/~brewer/cs262b-2004/PODC-keynote.pdf

Consistency

Availability Partition tolerance

Page 22: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

CAP定理• Webサービスでは「A」「P」は必須• 「C」で妥協するしかない

ここを工夫するConsistency

Availability Partition tolerance

Page 23: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

Consistency• Strong Consistency

- 誰かがデータを更新したら、次の人は必ず最新のデータにアクセスできる

• Weak Consistency- 誰かがデータを更新したら、次の人は必ず最新のデータにアクセスできる「とは限らない」

• Eventual Consistency- データが複製されるための十分な時間を経て、その後更新がされていなければ必ず最新のデータにアクセスできる

- MySQLのレプリケーションなんかもそうだよね

Page 24: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

ACIDからBASEへ?• ACID

Atomicity (原子性)/Consistency (一貫性)/Isolation (独立性、隔離性)/Durability (永続性)

• BASE- Basically (基本的に大丈夫)- Avaiable(使用可能であること) - Soft State (柔軟な状態管理。通信中に絶えず相手の動作を確認するインターネットのようなモデル)

- Eventual Consistency

Page 25: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

ACIDからBASEへ?• http://subtech.g.hatena.ne.jp/mala/20090303/1236054662

「正確さのために無駄なロックが発生したり、インデックスを肥大化させて、速度を犠牲にしてしまう。(よくあるパターンだと思う) 細かいことを気にしなければコンピューターの性能はもっと引き出せるはず。」(mala氏)

• どうしてもStrong Consistencyにしたい場合は実体/参照テーブルを同期書き込み、そうでもない場合は非同期書き込みにしておけば皆が幸せになれる。

Page 26: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

ここまでのまとめ• MySQLをkey-value storeとして使う、というアイデア

• 実際にFriend Feedで採用されている• 他のkey-value storeを採用するより信頼性やパフォーマンス、何より実績がある安心感

• 実体テーブルと参照テーブルを分けることにより一般的なRDBと同じような使い方ができる

MySQLでkey-value storeってありだよね!

Page 27: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

つづく

Page 28: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

MySQLへの接続問題• JDBCドライバ初期化→DB接続のオーバーヘッドが

Javaだと結構負担になる• 軽量言語では無問題かもしれないが・・・

• アプリ→MySQLで直接繋ぐと色々と問題が• セキュリティ問題(3306ポートを空ける?)• DBCPなどでpoolingさせると基本的にコネクションがステートフル状態になる

• あまり分散環境には向かない

Page 29: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

proxy

拠点B

拠点A

Proxy的な機能が有った方が便利なケースが多い

MySQL

MySQL

MySQL

MySQL

Proxy

Proxy

memcache

アプリ

アプリ

アプリ

負荷分散 負荷分散

クラスタリング

接続プール

キャッシュ

HTTPベースの接続

Page 30: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

Proxyのインターフェースをどうするか

• できればHTTP/ステートレス通信ベース• 標準技術である、NAT越え問題など

• とはいえREST、JSONなどのテキストベースではデータサイズのオーバーヘッドが大きい

Page 31: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

こんな記事

Page 32: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

こんな記事

Page 33: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

要約• AMF(Action Message Format)→AdobeがFlashで採用しているデータフォーマット バイナリベース。HTTP上でやり取りできる。 現在オープンソース化

• BlazeDS→LifeCycle Data Service ES(Flash リモーティングサーバ)のオープンソース版ミドルウェア。 AMF経由でのRPC、メッセージパッシングに対応

• BlazeDSはJava実装。Tomcat上で動作。• AMFはオープンソースのため、Java用のクライアント実装も公開されている

• Ajax+JSONより4倍速い?

Page 34: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

これだ

Page 35: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

パフォーマンス測定(BlazeDS × JSON)

• RPCサーバ側からクライアント側にHello World文字列を返却する処理を以下の方式で実装- 一般的なWebアプリケーション(SpringMVC。

GETのレスポンスで文字列を返却)- BlazeDS + SpringFramework + Java AMF Client で文字列返却(AMF経由でバイナリ通信)

- BlazeDS + SpringFramework + Java AMF Client でJavaオブジェクトをシリアライズして返却

Page 36: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

パフォーマンス測定(BlazeDS × JSON)

0

10,000

20,000

30,000

40,000

HTTP文字列 AMF文字列 AMオブジェクト

ステートレスステートフル

※1万回処理を実施※単位はミリ秒

Page 37: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

パフォーマンス測定(BlazeDS × JSON)

4倍速いっぽい

Page 38: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

パフォーマンス測定(JDBC × Proxy)

• クライアント側からDBにselect/insert/update/deleteの処理を以下の方式で実装- JDBCドライバを読み込み直接接続- singleton形式で初期化したDataSourceを使用し接続

- Proxy経由でAMF形式で接続(Proxy内ではDataSourceをsingletonで保持)

Page 39: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

0

1,000

2,000

3,000

4,000

JDBC直接 DataSource Proxy

insert updateselect delete

パフォーマンス測定(JDBC × Proxy)

※100回処理を実施※単位はミリ秒

Page 40: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

パフォーマンス測定(JDBC × Proxy)

• 直接DataSouceで接続するのに比べ、BlazeDSのProxy経由の方が若干遅い(通信オーバーヘッド分)

• しかしProxyの利便性により相殺できるレベル• Hadoop上のMap/Reduceタスクのように

singletonモデルが扱い辛い場合にProxy接続は便利

Page 41: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

パフォーマンス測定(Proxy × Tokyo Tyrant)

• Tokyo Cabinet / Tokyo Tyrant に対して先ほどの「JDBC×Proxy」と同様の処理を実施。※set(insert),get(select)のみ

Page 42: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

0

250

500

750

1,000

DataSource Proxy Tokyo Tyrant

put/insertget/select

パフォーマンス測定(Proxy×Tokyo Tyrant)

※100回処理を実施※単位はミリ秒

Page 43: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

パフォーマンス測定(Proxy × Tokyo Tyrant)

• Tokyo Tyrantの方が圧倒的に速い• 用途によっては、実体データをTokyo

Tyrantに保存する形で実装しても良さそう

Page 44: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

Tomcat

springframework

今回はBlazeDSを用いて以下のような構成に

MySQL

BlazeDS

アプリ

アプリ

アプリproxyサービス

スキーマレスDB接続

接続プール

HTTPベースの接続(AMF)

MyISAM

MySQL

レプリケーション

Page 45: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

現在取り扱っているデータ件数

データ更新 データ参照

データ量 350万/日 -

APIコール数 500万/日 1,550万/日

※4/19付けの結果※APIサーバ:1台※DBサーバ:1台

処理にはまだまだ余裕がある。

Page 46: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

BlazeDS使用の際の注意点• ステートフル通信をエミュレートするために、接続時にセッションオブジェクトが作成される。デフォルト設定で大量のリクエストを発行するとOut Of Memoryが発生する可能性がある。→セッションの保持期間を短くするか、セッション保持をしないようパッチを当てる(今回は前者で対応)

• RPC接続時にBlazeDS上でExceptionがthrowされてもクライアント側には通知されない→エラーコード等をクライアント側に返却する必要あり

Page 47: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

まとめ• MySQLでkey-value storeってありだよね• アプリ−MySQL間でProxy的な機能があると利便性が増す

• BlazeDSはTomcat上で動作、Java実装、AMFが扱えるということで便利。

• BlazeDS(AMF)のRPCはプレーンテキストのHTTPより4倍くらい速い

• 数千万ヒット/日:1台 程度の負荷は実用的に耐えられる実績も既にある。

Page 48: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

ご清聴ありがとうございました

Page 49: 小咄:BlazeDS+AMF Client+MySQLで実現するKey-Value Storage

質疑応答