handlersocket 20140218

37
HandlerSocket 2.0 2014/02/18 @ 渋渋渋渋渋渋 DeNA 渋渋渋渋渋渋渋 渋渋渋渋渋渋渋 渋渋渋 渋渋 ・・ 渋渋 渋

Upload: akirahiguchi

Post on 27-May-2015

3.347 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Handlersocket 20140218

HandlerSocket 2.0

2014/02/18 @  渋谷ヒカリエ DeNA セミナールーム

株式会社ディー・エヌ・エー樋口 証

Page 2: Handlersocket 20140218

3 行でまとめると

• HandlerSocket は、 MariaDB ・ MySQL の「非 SQL 」フロントエンド

• 性能向上、通信量削減、メモリ使用量削減等の効果がある

• version 2 でクエリ解釈ロジックを外部モジュールで定義できるようになり、従来よりも複雑なクエリをサポート

Page 3: Handlersocket 20140218

0

200000

400000

600000

800000

1000000

1200000

1 2 4 8 16 32 64 128

256

512

1024

2048

4096

8192

1638

4

3276

8

# of concurrent connections

quer

ies

per

seco

nd

SELECT querySELECT query (thread pool)HandlerSocket

Page 4: Handlersocket 20140218

HandlerSocket 開発のねらい

• DB キャッシュ用サーバを置くことによるシステムの複雑化や不整合問題を回避すること

• 予測可能で安定した性能を出すことで、性能問題起因のシステム障害を起こさないようにすること

• 同時接続数や通信量などのネックを回避し、システム全体のスケーラビリティを確保すること

Page 5: Handlersocket 20140218

基本的な情報

Page 6: Handlersocket 20140218

HandlerSocket を使うには

• MariaDB 5.3 以降に含まれている– MariaDB のサイトにドキュメントもある

https://mariadb.com/kb/en/handlersocket/

• インストール手順概略 :– my.cnf にいくつか設定を書く– 以下のクエリを実行し plugin をロード

install plugin handlersocket soname ‘handlersocket.so’

– telnet でポート 9998 に繋ぎ、改行を打つと反応が返ってくれば ok

Page 7: Handlersocket 20140218

構成

Handler Interface

Innodb MyISAM Other storage engines …

SQL Layer HandlerSocket Plugin

Listener for libmysqlclient

libmysqlclient libhsclient

Applications

mysqld

client app

port 3306port 9998, 9999

Page 8: Handlersocket 20140218

HandlerSocket クライアント

• 各言語のクライアントライブラリがあるhttps://github.com/DeNA/HandlerSocket-Plugin-for-MySQL

• プロトコルが単純なので、クライアントライブラリを使わずに実装することも可能

Page 9: Handlersocket 20140218

実行例

• create table db1.table1 (k int key, v char(20))• insert into db1.table1 values (234, 'foo'), (678, ‘bar’)

$ telnet localhost 9998Trying 127.0.0.1...Connected to localhost.Escape character is '^]'.P 0 db1 table1 PRIMARY k,v0 10 = 1 2340 2 234 foo0 = 1 6780 2 678 bar

db1.table1 の PK を開く

k = 234 を検索

k = 678 を検索

Page 10: Handlersocket 20140218

HandlerSocket の機能

Page 11: Handlersocket 20140218

HandlerSocket の主な機能 ( 参照系 )

• Primary Key や Unique Key を使った行取得

• 範囲取得– 比較条件に使える演算子は =, >=, >, <=, <

Page 12: Handlersocket 20140218

HandlerSocket の主な機能 ( 更新系 )

• 参照クエリで得た行の UPDATE と DELETE• 行の INSERT• Atomic な Increment/Decrement

• 更新系クエリは row-based の形式でバイナリログに記録される– MySQL のレプリケーション機能を使える

• ACID特性は MySQL と同じ– 書き込みは同期的、 ( 設定によるが )durable

Page 13: Handlersocket 20140218

MySQL と HandlerSocket の通信プロトコル比較

Page 14: Handlersocket 20140218

MySQL で通信内容が冗長になるケース

write(3, "L\0\0\0\3select column0,column1,column2,column3,column4 from db_1.table_1 where k=15", 80) = 80

read(3, "\1\0\0\1\0056\0\0\2\3def\4db_1\7table_1\7table_1\7column0\7column0\f\r\0<\0\0\0\375\200\0\0\0\0006\0\0\3\3def\4db_1\7table_1\7table_1\7column1\7column1\f\r\0<\0\0\0\375\200\0\0\0\0006\0\0\4\3def\4db_1\7table_1\7table_1\7column2\7column2\f\r\0<\0\0\0\375\200\0\0\0\0006\0\0\5\3def\4db_1\7table_1\7table_1\7column3\7column3\f\r\0<\0\0\0\375\200\0\0\0\0006\0\0\6\3def\4db_1\7table_1\7table_1\7column4\7column4\f\r\0<\0\0\0\375\200\0\0\0\0\5\0\0\7\376\0\0\"\0\n\0\0\10\0010\0011\0012\0013\0014\5\0\0\t\376\0\0\"\0", 16384) = 327

libmysqlclient/mysqld でこのクエリを実行すると…

SELECT column0, column1, column2, column3, column4 FROM db_1.table_1 where k = 15

Page 15: Handlersocket 20140218

MySQL で通信内容が冗長になるケース

write(3, "1\t=\t1\t15\n", 9) = 9read(3, "0\t5\t0\t1\t2\t3\t4\n", 8192) = 14

HandlerSocket で同等のクエリを実行すると…

libmysqlclient HandlerSocket

request 80 bytes 9 bytes

response 327 bytes 14 bytes

Page 16: Handlersocket 20140218

MySQL で通信内容が冗長になるケース

• 結果セットメタデータが大きい– 各列について、 DB名、テーブル名、テーブル別名、列名、列の別名がメタデータに含まれる

http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol#Field_Packet

– mysql 4.0 までのプロトコルではメタデータが少し小さい。 4.1以降で大きくなった。

• 列が多く行が少ないとき相対的に大きい– メタデータは結果セットに一つだけ付くから

• HANDLER クエリや SSPS を使っても減らすことができない

Page 17: Handlersocket 20140218

MySQL の性能を引き出すためのその他の機能

Page 18: Handlersocket 20140218

MariaDB の thread pool について

• MariaDB には thread pool の実装がある (既定では off)thread-handling=pool-of-threads

• 有効にすると SQL クエリについても同時接続数を増やしたときの性能劣化が小さくなる– HandlerSocket を使った場合と似た特性になる

• 但し HandlerSocket を使うときは thread pool無効にしておいたほうがよいかもしれない– sleep しうる処理は one-thread-per-connection のほ

うが向いている

Page 19: Handlersocket 20140218

0

20000

40000

60000

80000

100000

120000

140000

160000

180000

200000

1 2 4 8 16 32 64 128

256

512

1024

2048

4096

8192

1638

4

3276

8

# of concurrent connections

quer

ies

per

seco

nd

SELECT query

SELECT query (thread pool)

Page 20: Handlersocket 20140218

HANDLER クエリ

• 索引に対する低レベルアクセスを行うクエリ

• 参照クエリのみサポート• SELECT クエリよりも速いことが多い• ただし取得する列を指定することができ

ず、常に全フィールド取得になってしまう

Page 21: Handlersocket 20140218

Server-Side Prepared Statement

• 少しだけ性能が上がることがある

Page 22: Handlersocket 20140218

HandlerSocket リクエストの pipelining

• HandlerSocket プロトコルは pipeline 化可能– HandlerSocket の実装は pipeline 化されたリ

クエストに対して最適化されている• プロトコルは単純な行ベースなので、接

続を集約して pipeline 化するプロキシを簡単に作れる

Page 23: Handlersocket 20140218

0

500000

1000000

1500000

2000000

2500000

1 2 4 8 16 32 64 128

256

512

1024

2048

4096

8192

1638

4

3276

8

# of concurrent connections

quer

ies

per

seco

nd

SELECT querySELECT query (thread pool)HandlerSocketHandlerSocket (pipelining x5)HANDLER query (thread pool)HANDLER query SSPS (thread pool)

Page 24: Handlersocket 20140218

ベンチマークについて• Xeon E5-2670 2.6GHz, 16core 32論理 CPU の半分を mysqld, 半分をクライアントに割り当て

• internet domain socket で通信• innodb テーブル• innodb_adaptive_hash_index = 1• handlersocket_threads = 16

Page 25: Handlersocket 20140218

HandlerSocket 2.0 について

Page 26: Handlersocket 20140218

version 2.0 の変更点

• クエリ解釈ロジックを外部モジュールで定義できるようになる– 従来サポートしていなかった種類のクエリを

外部モジュールで実装可能• 外部モジュールは、サービスを停止せず

に更新可能–古いバージョンの外部モジュールは参照が無

くなった時点でアンロードされる

Page 27: Handlersocket 20140218

ねらい• Stored procedure のように手軽に HandlerSock

etへ機能追加できるようにしたい• SQL に代わるクエリ言語を外部モジュールとし

て実装する– 従来の HandlerSocket クエリは拡張性に乏しいので抜本的に直したい

• 将来的には SQL も HandlerSocket 上に実装するかもしれない– SQL であっても現在の HandlerSocket と同等の性能

を出すことは可能

Page 28: Handlersocket 20140218

構成

Handler Interface

Storage engines

Transaction management etc.hs module

HandlerSocket Listener

API for hs modules

clients

prepare, execute response

find, update, etc. result

port 9998, 9999

Page 29: Handlersocket 20140218

hs module

hsmod_module

hsmod_worker

hsmod_conn

hsmod_stmt

モジュールがロードされたときに 1 つだけ作成される

ワーカースレッドにつき 1 つ作成される

クライアント接続につき 1 つ作成される

ステートメントが prepare されるごとに作成されるクエリが実行されると execute メソッドが呼ばれる

prepare

create

create

Page 30: Handlersocket 20140218

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 クライアントへレスポンスを返す

Page 31: Handlersocket 20140218

hsmod_pxc

• HS2.0 クエリ (仮 ) を実行する hs module 実装

• コンパイルに pxc が必要https://github.com/ahiguti/pxc

Page 32: Handlersocket 20140218

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 = ?

Page 33: Handlersocket 20140218

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 = ?

Page 34: Handlersocket 20140218

0

200000

400000

600000

800000

1000000

1200000

1 2 4 8 16 32 64 128

256

512

1024

2048

4096

8192

1638

4

# of concurrent connections

quer

ies

per

seco

nd

HS2.0, simple queryHS2.0, inner join

Page 35: Handlersocket 20140218

version 2.0 でもできないこと

• 自動コミットを抑制はできない– HandlerSocket ではレスポンスが返った時点

で必ずコミット済み– lock を保持したまま sleep することが無いよ

うにしている• rollback はできない

– 複数リクエストを一つのトランザクションの中で実行しているから

Page 36: Handlersocket 20140218

SQL をサポート?

• SQL をパースし、実行戦略を決めて HS2.0 クエリ (仮 ) を組み立てればよい

• 変換は prepare段階で行えるので、 execute の性能には影響しない– したがって SQL であっても現在の HandlerS

ocket と同等の性能を出すことができる• 実装するかどうか未定

Page 37: Handlersocket 20140218

• 以下のブランチで開発中https://code.launchpad.net/~maria-captains/maria/10.0-hs-devel

• 移動するかも。その場合は以下のアドレスから辿れるようにする。https://launchpad.net/~ahiguti100