Handlersocket 20140218
Upcoming SlideShare
Loading in...5
×
 

Handlersocket 20140218

on

  • 1,649 views

 

Statistics

Views

Total Views
1,649
Views on SlideShare
1,646
Embed Views
3

Actions

Likes
1
Downloads
8
Comments
0

1 Embed 3

https://twitter.com 3

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Handlersocket 20140218 Handlersocket 20140218 Presentation Transcript

  • HandlerSocket 2.0 2014/02/18 @  渋谷ヒカリエ DeNA セミナールーム 株式会社ディー・エヌ・エー 樋口 証
  • 3 行でまとめると • HandlerSocket は、 MariaDB ・ MySQL の 「非 SQL 」フロントエンド • 性能向上、通信量削減、メモリ使用量削減 等の効果がある • version 2 でクエリ解釈ロジックを外部モ ジュールで定義できるようになり、従来よ りも複雑なクエリをサポート
  • 1 200000 SELEC T q u e r y SELEC T q u e r y (t h r e a d p o o l) Ha n d le r So c k e t 800000 600000 400000 200000 # o f c o n c u rre n t c o n n e c t io n s 32768 1 6384 81 92 4096 2048 1 024 51 2 256 1 28 64 32 16 8 4 2 0 1 q u e rie s p e r s e c o n d 1 000000
  • HandlerSocket 開発のねらい • DB キャッシュ用サーバを置くことによる システムの複雑化や不整合問題を回避する こと • 予測可能で安定した性能を出すことで、性 能問題起因のシステム障害を起こさないよ うにすること • 同時接続数や通信量などのネックを回避し 、システム全体のスケーラビリティを確保 すること
  • 基本的な情報
  • HandlerSocket を使うには • MariaDB 5.3 以降に含まれている – MariaDB のサイトにドキュメントもある https://mariadb.com/kb/en/handlersocket/ • インストール手順概略 : – my.cnf にいくつか設定を書く – 以下のクエリを実行し plugin をロード install plugin handlersocket soname ‘handlersocket.so’ – telnet でポート 9998 に繋ぎ、改行を打つと反 応が返ってくれば ok
  • 構成 client app Applications libmysqlclient libhsclient port 3306 port 9998, 9999 Listener for libmysqlclient mysqld SQL Layer HandlerSocket Plugin Handler Interface Innodb MyISAM Other storage engines …
  • HandlerSocket クライアント • 各言語のクライアントライブラリがある https://github.com/DeNA/HandlerSocket-Plugin-for-MySQL • プロトコルが単純なので、クライアント ライブラリを使わずに実装することも可 能
  • 実行例 • create table db1.table1 (k int key, v char(20)) • insert into db1.table1 values (234, 'foo'), (678, ‘bar’) $ telnet localhost 9998 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. P 0 db1 table1 PRIMARY k,v 0 1 0 = 1 234 0 2 234 foo 0 = 1 678 0 2 678 bar db1.table1 の PK を開く k = 234 を検索 k = 678 を検索
  • HandlerSocket の機能
  • HandlerSocket の主な機能 ( 参照 系) • Primary Key や Unique Key を使った行取 得 • 範囲取得 – 比較条件に使える演算子は =, >=, >, <=, <
  • HandlerSocket の主な機能 ( 更新 系) • 参照クエリで得た行の UPDATE と DELETE • 行の INSERT • Atomic な Increment/Decrement • 更新系クエリは row-based の形式でバイナリロ グに記録される – MySQL のレプリケーション機能を使える • ACID 特性は MySQL と同じ – 書き込みは同期的、 ( 設定によるが )durable
  • MySQL と HandlerSocket の通信プ ロトコル比較
  • MySQL で通信内容が冗長になるケース SELECT column0, column1, column2, column3, column4 FROM db_1.table_1 where k = 15 libmysqlclient/mysqld でこのクエリを実行すると… write(3, "L0003select column0,column1,column2,column3,column4 from db_1.table_1 where k=15", 80) = 80 read(3, "100100560023def4db_17table_17table_17column0 7column0fr0<00037520000000060033def4db_17 table_17table_17column17column1fr0<00037520000 000060043def4db_17table_17table_17column27column 2fr0<00037520000000060053def4db_17table_1 7table_17column37column3fr0<0003752000000006 0063def4db_17table_17table_17column47column4fr0 <0003752000000500737600"0n001000100 011001200130014500t37600"0", 16384) = 327
  • MySQL で通信内容が冗長になるケース HandlerSocket で同等のクエリを実行すると… write(3, "1t=t1t15n", 9) read(3, "0t5t0t1t2t3t4n", 8192) = 9 = 14 libmysqlclient HandlerSocket request 80 bytes 9 bytes response 327 bytes 14 bytes
  • MySQL で通信内容が冗長になるケース • 結果セットメタデータが大きい – 各列について、 DB 名、テーブル名、テーブル別名、列名、列の 別名がメタデータに含まれる http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol#F – mysql 4.0 までのプロトコルではメタデータが少し小さい。 4.1 以 降で大きくなった。 • 列が多く行が少ないとき相対的に大きい – メタデータは結果セットに一つだけ付くから • HANDLER クエリや SSPS を使っても減らすこと ができない
  • MySQL の性能を引き出すため のその他の機能
  • MariaDB の thread pool につい て • MariaDB には thread pool の実装がある ( 既定 では off) thread-handling=pool-of-threads • 有効にすると SQL クエリについても同時接続 数を増やしたときの性能劣化が小さくなる – HandlerSocket を使った場合と似た特性になる • 但し HandlerSocket を使うときは thread pool 無 効にしておいたほうがよいかもしれない – sleep しうる処理は one-thread-per-connection のほう が向いている
  • 200000 1 80000 1 40000 1 20000 1 00000 80000 60000 40000 SELEC T q u e r y 20000 SELEC T q u e r y (t h r e a d p o o l) # o f c o n c u rre n t c o n n e c t io n s 32768 1 6384 81 92 4096 2048 1 024 51 2 256 1 28 64 32 16 8 4 2 0 1 q u e rie s p e r s e c o n d 1 60000
  • HANDLER クエリ • 索引に対する低レベルアクセスを行うク エリ • 参照クエリのみサポート • SELECT クエリよりも速いことが多い • ただし取得する列を指定することができ ず、常に全フィールド取得になってしま う
  • Server-Side Prepared Statement • 少しだけ性能が上がることがある
  • HandlerSocket リクエストの pipelining • HandlerSocket プロトコルは pipeline 化可 能 – HandlerSocket の実装は pipeline 化されたリ クエストに対して最適化されている • プロトコルは単純な行ベースなので、接 続を集約して pipeline 化するプロキシを簡 単に作れる
  • 2500000 S EL EC T q u e r y S EL EC T q u e r y (t h r e a d p o o l) Ha n d le r S o c k e t Ha n d le r S o c k e t (p ip e lin in g x 5) HANDL ER q u e r y (t h r e a d p o o l) HANDL ER q u e r y S S PS (t h r e a d p o o l) 1 500000 1 000000 500000 # o f c o n c u rre n t c o n n e c t io n s 32768 1 6384 81 92 4096 2048 1 024 51 2 256 1 28 64 32 16 8 4 2 0 1 q u e rie s p e r s e c o n d 2000000
  • ベンチマークについて • Xeon E5-2670 2.6GHz, 16core 32 論理 CPU の 半分を mysqld, 半分をクライアントに割り当て • internet domain socket で通信 • innodb テーブル • innodb_adaptive_hash_index = 1 • handlersocket_threads = 16
  • HandlerSocket 2.0 について
  • version 2.0 の変更点 • クエリ解釈ロジックを外部モジュールで 定義できるようになる – 従来サポートしていなかった種類のクエリを 外部モジュールで実装可能 • 外部モジュールは、サービスを停止せず に更新可能 – 古いバージョンの外部モジュールは参照が無 くなった時点でアンロードされる
  • ねらい • Stored procedure のように手軽に HandlerSocket へ機能追加できるようにしたい • SQL に代わるクエリ言語を外部モジュールとし て実装する – 従来の HandlerSocket クエリは拡張性に乏しいので 抜本的に直したい • 将来的には SQL も HandlerSocket 上に実装する かもしれない – SQL であっても現在の HandlerSocket と同等の性能 を出すことは可能
  • 構成 clients port 9998, 9999 HandlerSocket Listener prepare, execute response hs module Transaction management etc. find, update, etc. result API for hs modules Handler Interface Storage engines
  • hs module hsmod_module モジュールがロードされたときに 1 つだけ作成される hsmod_worker ワーカースレッドにつき 1 つ作成される hsmod_conn クライアント接続につき 1 つ作成される hsmod_stmt ステートメントが prepare されるごとに作成される クエリが実行されると execute メソッドが呼ばれる create create prepare
  • API for hs modules 関数 コンテキスト 動作 hs_open_index prepare テーブルと索引を開く hs_get_field_num prepare, execute 指定された名前のフィールドを捜し、その番号を 返す hs_find_first hs_find_next hs_find_finish execute 索引から条件にマッチするレコードを探す hs_field_get execute 現在選択されている行の指定された列の値を取得 hs_update_row execute 現在選択されている行を指定された値で更新 hs_delete_row execute 現在選択されている行を削除 hs_insert_row execute 行を作成 hs_push_response prepare, execute クライアントへレスポンスを返す
  • hsmod_pxc • HS2.0 クエリ ( 仮 ) を実行する hs module 実装 • コンパイルに pxc が必要 https://github.com/ahiguti/pxc
  • HS2.0 クエリ ( 仮 ) – 単純なク エリ (do (open hstestdb hstesttbl PRIMARY idx0) (foreach idx0 = (?0) 1 (response (idx0.v)))) テーブル hstestdb.hstesttbl の PK を開き、 idx0 という名前をつ ける。 idx0 のキーが実行時引数の 0 番に一致する行に対 し、その行のフィールド v の値を返す。 これは以下の SQL クエリと同等の結果を返す SELECT v from hstestdb.hstesttbl where k = ?
  • HS2.0 クエリ ( 仮 ) – inner join (do (open hstestdb hstesttbl PRIMARY idx0) (open hstestdb hst2 PRIMARY idx1) (foreach idx0 = (?0) 1 (foreach idx1 = (idx0.v) 1 (response (idx0.k idx0.v idx1.k idx1.v))))) これは以下の SQL クエリと同等の結果を返す SELECT t0.k, t0.v, t1.k, t1.v FROM hstestdb.hstesttbl t0 INNER JOIN hstestdb.hst2 t1 ON t0.v = t1.k WHERE t0.k = ?
  • 1 200000 HS2.0, s im p le q u e r y HS2.0, in n e r jo in 800000 600000 400000 200000 # o f c o n c u rre n t c o n n e c t io n s 1 6384 81 92 4096 2048 1 024 51 2 256 1 28 64 32 16 8 4 2 0 1 q u e rie s p e r s e c o n d 1 000000
  • version 2.0 でもできないこと • 自動コミットを抑制はできない – HandlerSocket ではレスポンスが返った時点 で必ずコミット済み – lock を保持したまま sleep することが無いよ うにしている • rollback はできない – 複数リクエストを一つのトランザクションの 中で実行しているから
  • SQL をサポート? • SQL をパースし、実行戦略を決めて HS2.0 クエリ ( 仮 ) を組み立てればよい • 変換は prepare 段階で行えるの で、 execute の性能には影響しない – したがって SQL であっても現在の HandlerSocket と同等の性能を出すことがで きる • 実装するかどうか未定
  • • 以下のブランチで開発中 https://code.launchpad.net/~maria-captains/maria/10 • 移動するかも。その場合は以下のアドレ スから辿れるようにする。 https://launchpad.net/~ahiguti100