Handlersocket 20140218

5,828 views
5,524 views

Published on

0 Comments
13 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
5,828
On SlideShare
0
From Embeds
0
Number of Embeds
666
Actions
Shares
0
Downloads
24
Comments
0
Likes
13
Embeds 0
No embeds

No notes for slide

Handlersocket 20140218

  1. 1. HandlerSocket 2.0 2014/02/18 @  渋谷ヒカリエ DeNA セミナールーム 株式会社ディー・エヌ・エー 樋口 証
  2. 2. 3 行でまとめると • HandlerSocket は、 MariaDB ・ MySQL の 「非 SQL 」フロントエンド • 性能向上、通信量削減、メモリ使用量削減 等の効果がある • version 2 でクエリ解釈ロジックを外部モ ジュールで定義できるようになり、従来よ りも複雑なクエリをサポート
  3. 3. 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
  4. 4. HandlerSocket 開発のねらい • DB キャッシュ用サーバを置くことによる システムの複雑化や不整合問題を回避する こと • 予測可能で安定した性能を出すことで、性 能問題起因のシステム障害を起こさないよ うにすること • 同時接続数や通信量などのネックを回避し 、システム全体のスケーラビリティを確保 すること
  5. 5. 基本的な情報
  6. 6. HandlerSocket を使うには • MariaDB 5.3 以降に含まれている – MariaDB のサイトにドキュメントもある https://mariadb.com/kb/en/handlersocket/ • インストール手順概略 : – my.cnf にいくつか設定を書く – 以下のクエリを実行し plugin をロード install plugin handlersocket soname ‘handlersocket.so’ – telnet でポート 9998 に繋ぎ、改行を打つと反 応が返ってくれば ok
  7. 7. 構成 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 …
  8. 8. HandlerSocket クライアント • 各言語のクライアントライブラリがある https://github.com/DeNA/HandlerSocket-Plugin-for-MySQL • プロトコルが単純なので、クライアント ライブラリを使わずに実装することも可 能
  9. 9. 実行例 • 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 を検索
  10. 10. HandlerSocket の機能
  11. 11. HandlerSocket の主な機能 ( 参照 系) • Primary Key や Unique Key を使った行取 得 • 範囲取得 – 比較条件に使える演算子は =, >=, >, <=, <
  12. 12. HandlerSocket の主な機能 ( 更新 系) • 参照クエリで得た行の UPDATE と DELETE • 行の INSERT • Atomic な Increment/Decrement • 更新系クエリは row-based の形式でバイナリロ グに記録される – MySQL のレプリケーション機能を使える • ACID 特性は MySQL と同じ – 書き込みは同期的、 ( 設定によるが )durable
  13. 13. MySQL と HandlerSocket の通信プ ロトコル比較
  14. 14. 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
  15. 15. 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
  16. 16. MySQL で通信内容が冗長になるケース • 結果セットメタデータが大きい – 各列について、 DB 名、テーブル名、テーブル別名、列名、列の 別名がメタデータに含まれる http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol#F – mysql 4.0 までのプロトコルではメタデータが少し小さい。 4.1 以 降で大きくなった。 • 列が多く行が少ないとき相対的に大きい – メタデータは結果セットに一つだけ付くから • HANDLER クエリや SSPS を使っても減らすこと ができない
  17. 17. MySQL の性能を引き出すため のその他の機能
  18. 18. MariaDB の thread pool につい て • MariaDB には thread pool の実装がある ( 既定 では off) thread-handling=pool-of-threads • 有効にすると SQL クエリについても同時接続 数を増やしたときの性能劣化が小さくなる – HandlerSocket を使った場合と似た特性になる • 但し HandlerSocket を使うときは thread pool 無 効にしておいたほうがよいかもしれない – sleep しうる処理は one-thread-per-connection のほう が向いている
  19. 19. 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
  20. 20. HANDLER クエリ • 索引に対する低レベルアクセスを行うク エリ • 参照クエリのみサポート • SELECT クエリよりも速いことが多い • ただし取得する列を指定することができ ず、常に全フィールド取得になってしま う
  21. 21. Server-Side Prepared Statement • 少しだけ性能が上がることがある
  22. 22. HandlerSocket リクエストの pipelining • HandlerSocket プロトコルは pipeline 化可 能 – HandlerSocket の実装は pipeline 化されたリ クエストに対して最適化されている • プロトコルは単純な行ベースなので、接 続を集約して pipeline 化するプロキシを簡 単に作れる
  23. 23. 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
  24. 24. ベンチマークについて • Xeon E5-2670 2.6GHz, 16core 32 論理 CPU の 半分を mysqld, 半分をクライアントに割り当て • internet domain socket で通信 • innodb テーブル • innodb_adaptive_hash_index = 1 • handlersocket_threads = 16
  25. 25. HandlerSocket 2.0 について
  26. 26. version 2.0 の変更点 • クエリ解釈ロジックを外部モジュールで 定義できるようになる – 従来サポートしていなかった種類のクエリを 外部モジュールで実装可能 • 外部モジュールは、サービスを停止せず に更新可能 – 古いバージョンの外部モジュールは参照が無 くなった時点でアンロードされる
  27. 27. ねらい • Stored procedure のように手軽に HandlerSocket へ機能追加できるようにしたい • SQL に代わるクエリ言語を外部モジュールとし て実装する – 従来の HandlerSocket クエリは拡張性に乏しいので 抜本的に直したい • 将来的には SQL も HandlerSocket 上に実装する かもしれない – SQL であっても現在の HandlerSocket と同等の性能 を出すことは可能
  28. 28. 構成 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
  29. 29. hs module hsmod_module モジュールがロードされたときに 1 つだけ作成される hsmod_worker ワーカースレッドにつき 1 つ作成される hsmod_conn クライアント接続につき 1 つ作成される hsmod_stmt ステートメントが prepare されるごとに作成される クエリが実行されると execute メソッドが呼ばれる create create prepare
  30. 30. 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 クライアントへレスポンスを返す
  31. 31. hsmod_pxc • HS2.0 クエリ ( 仮 ) を実行する hs module 実装 • コンパイルに pxc が必要 https://github.com/ahiguti/pxc
  32. 32. 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 = ?
  33. 33. 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 = ?
  34. 34. 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
  35. 35. version 2.0 でもできないこと • 自動コミットを抑制はできない – HandlerSocket ではレスポンスが返った時点 で必ずコミット済み – lock を保持したまま sleep することが無いよ うにしている • rollback はできない – 複数リクエストを一つのトランザクションの 中で実行しているから
  36. 36. SQL をサポート? • SQL をパースし、実行戦略を決めて HS2.0 クエリ ( 仮 ) を組み立てればよい • 変換は prepare 段階で行えるの で、 execute の性能には影響しない – したがって SQL であっても現在の HandlerSocket と同等の性能を出すことがで きる • 実装するかどうか未定
  37. 37. • 以下のブランチで開発中 https://code.launchpad.net/~maria-captains/maria/10 • 移動するかも。その場合は以下のアドレ スから辿れるようにする。 https://launchpad.net/~ahiguti100

×