Handlersocket etc. 20110906

4,949 views

Published on

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

No Downloads
Views
Total views
4,949
On SlideShare
0
From Embeds
0
Number of Embeds
722
Actions
Shares
0
Downloads
43
Comments
0
Likes
7
Embeds 0
No embeds

No notes for slide

Handlersocket etc. 20110906

  1. 1. HandlerSocket について + α 2011/09/06 tokyoLinuxStudy #3   @  四谷 株式会社ディー・エヌ・エー システム統括本部 IT 基盤部 樋口 証
  2. 2. HandlerSocket plugin とは <ul><li>MySQL の NoSQL なインタフェース </li></ul><ul><li>○ NoSQL </li></ul><ul><li>× NoRDB </li></ul>
  3. 3. 構成 mysqld client app Handler Interface Innodb MyISAM Other storage engines … SQL Layer HandlerSocket Plugin Listener for libmysql libmysql libhsclient Applications
  4. 4. 概要 <ul><li>InnoDB 等のストレージエンジンへの非 SQL インタフェースを提供 </li></ul><ul><li>TCP/IP でリクエストを受け、ストレージエンジンを直接叩く </li></ul><ul><li>独自プロトコルを喋る </li></ul><ul><li>C++ と Perl のクライアントライブラリを用意 </li></ul><ul><ul><li>PHP, Java, Python, Ruby, JavaScript(node.js), Scala のライブラリが存在 </li></ul></ul><ul><li>Linux/FreeBSD/MacOS で動作 </li></ul><ul><ul><li>Linux に最もチューニングされている </li></ul></ul><ul><li>BSD ライセンス </li></ul><ul><li>ソース : https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL </li></ul>
  5. 5. 入手&インストール方法 <ul><li>ソースからビルド </li></ul><ul><ul><li>https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL </li></ul></ul><ul><li>Spider For MySQL に同梱されている </li></ul><ul><ul><li>http://spiderformysql.com/ </li></ul></ul><ul><ul><li>斯波さんによる様々な機能追加有り </li></ul></ul><ul><li>Percona Server に同梱されている </li></ul><ul><ul><li>http://www.percona.com/software/percona-server/downloads/ </li></ul></ul>
  6. 6. メリット <ul><li>速い </li></ul><ul><ul><li>MySQL は SQL をパースする処理周辺が性能のネックになることがある </li></ul></ul><ul><ul><li>HandlerSocket はリクエストを集約実行できる </li></ul></ul><ul><ul><li>HandlerSocket はリクエストをパイプライン化できる </li></ul></ul><ul><ul><li>クライアントライブラリも速い </li></ul></ul><ul><li>同時接続数がほとんど無制限に </li></ul><ul><ul><li>65536 本くらいまでいける </li></ul></ul><ul><li>通信量が減る </li></ul>
  7. 7. HandlerSocket に向いているケース <ul><li>データサイズが十分小さくメモリに乗る </li></ul><ul><li>単純なクエリ、サーバの CPU がネック </li></ul><ul><li>単純なクエリ、トラフィックがネック </li></ul><ul><li>同時接続数が多すぎて MySQL の持続接続が使えない </li></ul>
  8. 8. HandlerSocket に不向きなケース <ul><li>クエリが複雑で HandlerSocket で実現困難 </li></ul><ul><li>クエリ一回あたりの CPU 使用量が多く CPU ネック </li></ul><ul><li>データサイズが大きく Disk IO がネック </li></ul>
  9. 9. 性能の目安 ( 参照系 ) <ul><li>8 Core CPU with HT 、 1Gb の NIC x1 、 InnoDB plugin 、単純な参照クエリの処理性能 </li></ul><ul><ul><li>libmysql: ~ 100,000 qps </li></ul></ul><ul><ul><ul><li>CPU ネック </li></ul></ul></ul><ul><ul><li>HandlerSocket: ~ 300,000 qps </li></ul></ul><ul><ul><ul><li>ネットワーク周りがネックになる </li></ul></ul></ul><ul><ul><ul><li>CPU は頭打たない </li></ul></ul></ul><ul><ul><li>HandlerSocket(pipelined): ~ 800,000 qps </li></ul></ul><ul><ul><ul><li>CPU ネック </li></ul></ul></ul><ul><ul><li>HandlerSocket(pipelined) AHI 有効 : ~ 3,000,000 qps </li></ul></ul><ul><ul><ul><li>CPU ネック </li></ul></ul></ul>
  10. 10. 性能の目安 ( 更新系 ) <ul><li>前提 : </li></ul><ul><ul><li>同期 (durable) 書き込み </li></ul></ul><ul><ul><ul><li>sync_binlog = 1 </li></ul></ul></ul><ul><ul><ul><li>innodb_flush_log_at_trx_commit = 1 </li></ul></ul></ul><ul><ul><ul><li>innodb_support_xa = 1 </li></ul></ul></ul><ul><ul><li>バッテリ付き write-back cache 又は SSD </li></ul></ul><ul><li>性能 : </li></ul><ul><ul><li>mysql: ~ 1000 qps </li></ul></ul><ul><ul><ul><li>innodb plugin で sync_binlog = 0 だと group commit が効いてさらに速くなるが、レプリするとスレーブが追いつかない </li></ul></ul></ul><ul><ul><li>HandlerSocket: ~ 30000 qps </li></ul></ul><ul><ul><ul><li>書き込みはシリアライズされるので、レプリしても常にスレーブが追いつく </li></ul></ul></ul>
  11. 11. HandlerSocket の主な機能 ( 参照系 ) <ul><li>Index を使った行取得 </li></ul><ul><ul><li>Index を使った取得しかできない </li></ul></ul><ul><li>範囲取得 </li></ul><ul><ul><li>比較条件に使える演算子は =, >=, >, <=, < </li></ul></ul><ul><li>SQL の’ IN’ のような複数行取得 </li></ul><ul><li>範囲取得 + フィルタ </li></ul><ul><ul><li>条件を満たす行だけを取得 </li></ul></ul>
  12. 12. HandlerSocket の主な機能 ( 更新系 ) <ul><li>参照クエリで得た行の UPDATE と DELETE </li></ul><ul><li>行の INSERT </li></ul><ul><li>Atomic な Increment/Decrement </li></ul><ul><li>トランザクションはサポートしない </li></ul><ul><li>リクエストを跨いだレコードロックを取ることはできない </li></ul><ul><ul><li>つまり select ... for update </li></ul></ul>
  13. 13. SQL クエリとの共存 <ul><li>○ 同じ DB を SQL と HandlerSocket の両方からアクセスできる </li></ul><ul><li>○ バイナリログ </li></ul><ul><ul><li>HandlerSocket による更新は row base のバイナリログエントリとして記録される </li></ul></ul><ul><li>○ レプリケーション </li></ul><ul><li>○ SQL クエリキャッシュ </li></ul><ul><ul><li>HandlerSocket で更新するとクエリキャッシュが破棄される </li></ul></ul><ul><ul><li>古い HandlerSocket では破棄されない問題があった </li></ul></ul><ul><li>○ ACID 特性 </li></ul><ul><li>○ AUTO_INCREMENT </li></ul><ul><ul><li>HandlerSocket で NULL をセットすると一意な値が生成される </li></ul></ul><ul><li>× TIMESTAMP 型 </li></ul><ul><ul><li>HandlerSocket での更新では値がセットされない </li></ul></ul><ul><li>× トリガ </li></ul><ul><ul><li>HandlerSocket での更新ではトリガは実行されない </li></ul></ul>
  14. 14. はまりどころ (1) <ul><li>HandlerSocket の接続を切るまでテーブルが閉じられない </li></ul><ul><ul><li>ALTER TABLE とか打つときは接続を全部閉じる必要がある </li></ul></ul>
  15. 15. はまりどころ (2) <ul><li>SQL と HandlerSocket の両方から同じ DB を更新するとデッドロックすることがある </li></ul><ul><ul><li>SQL で更新する際に次のように排他処理するとデッドロックしない </li></ul></ul><ul><ul><li>SELECT GET_LOCK(‘handlersocket_wr’, 5); </li></ul></ul><ul><ul><li>(SQL による更新処理 ) </li></ul></ul><ul><ul><li>SELECT RELEASE_LOCK(‘handlersocket_wr’); </li></ul></ul>
  16. 16. libhsclient <ul><li>HandlerSocket 用クライアントライブラリ </li></ul><ul><ul><li>C++ </li></ul></ul><ul><ul><li>低水準インタフェース </li></ul></ul>
  17. 17. Net::HandlerSocket <ul><li>Perl 用クライアントライブラリ </li></ul><ul><ul><li>xs 経由で libhsclient を呼んでいる </li></ul></ul>my $cli = new Net::HandlerSocket( {host => ‘localhost’, port => 9999}); $cli->open_index(1, ‘db1’, ‘table1’, ‘PRIMARY’, ‘k,v’); my $res = $cli->exec_multi([ [ 1, ‘=‘, [ ’33’ ], 1, 0 ], [ 1, ‘=‘, [ ’44’ ], 1, 0, ‘U’, [ ’44’, ‘hoge’ ] ], [ 1, ‘>=‘, [ ’55’ ], 10, 20 ], ]);
  18. 18. その他の言語用クライアントライブラリ <ul><li>PHP </li></ul><ul><ul><li>http://openpear.org/package/Net_HandlerSocket </li></ul></ul><ul><ul><li>http://github.com/tz-lom/HSPHP </li></ul></ul><ul><ul><li>http ://code.google.com/p/php-handlersocket/ </li></ul></ul><ul><li>Java </li></ul><ul><ul><li>http://code.google.com/p/hs4j/ </li></ul></ul><ul><ul><li>http ://code.google.com/p/handlersocketforjava/ </li></ul></ul><ul><li>Python </li></ul><ul><ul><li>http://pypi.python.org/pypi/python-handler-socket </li></ul></ul><ul><ul><li>https ://code.launchpad.net/~songofacandy/+junk/pyhandlersocket </li></ul></ul><ul><li>Ruby </li></ul><ul><ul><li>https://github.com/winebarrel/ruby-handlersocket </li></ul></ul><ul><ul><li>https ://github.com/miyucy/handlersocket </li></ul></ul><ul><li>JavaScript </li></ul><ul><ul><li>https://github.com/koichik/node-handlersocket </li></ul></ul><ul><li>Scala </li></ul><ul><ul><li>https://github.com/fujohnwang/hs2client </li></ul></ul>
  19. 19. Mobage での負荷分散と冗長化
  20. 20. Mobage での負荷分散 & 冗長化 (1) MySQL アプリサーバ MyDNS サーバ MySQL MySQL MySQL サーバのリストを取得
  21. 21. Mobage での負荷分散 & 冗長化 (2) MySQL アプリサーバ MyDNS サーバ MySQL MySQL 一台を選択しクエリ実行
  22. 22. Mobage での負荷分散 & 冗長化 (3) MySQL アプリサーバ MyDNS サーバ MySQL MySQL エラーが起きたら次を試す
  23. 23. Mobage での負荷分散と冗長化 <ul><li>サーバリストの各エントリには重みが指定可能 </li></ul><ul><ul><li>少しずつサービスに入れるようなことができる </li></ul></ul><ul><ul><li>性能の異なるサーバを混ぜられる </li></ul></ul><ul><li>サーバリストは 10 秒に一回程度の頻度で取得 </li></ul><ul><li>ランダム又は consistent hashing でサーバを決定する </li></ul><ul><li>DB 接続はなるべく持続 </li></ul><ul><ul><li>HandlerSocket では 30 秒間繋ぎっぱなし </li></ul></ul><ul><li>アプリ自体がリトライする仕組みを持っている </li></ul><ul><ul><li>DB サーバが一台死んでも即エラーにはならない </li></ul></ul><ul><li>DB サーバ以外も同じ仕組みで負荷分散&冗長化 </li></ul>
  24. 24. Mobage での負荷分散と冗長化 <ul><li>Mobage で使っている仕組みの一部が HandlerSocket のソースに入っています </li></ul><ul><ul><li>perl-Net-HandlerSocket/lib/Net/HandlerSocket/Pool.pm </li></ul></ul><ul><ul><li>持続接続、エラー時のリトライ処理など </li></ul></ul>
  25. 25. まとめ <ul><li>HandlerSocket を使えば MySQL のデータベースアクセスを高速化できることがあります </li></ul><ul><li>性能を引き出すには負荷分散・冗長化の仕組みも重要です </li></ul>

×