SlideShare a Scribd company logo
HandlerSocket plugin for MySQL 2011/05/17  NoSQL セミナー @ 渋谷 株式会社 DeNA  システム統括本部  IT 基盤部 樋口 証  <higuchi dot akira at dena dot jp>
概要
HandlerSocket plugin とは MySQL の非 SQL なインタフェース ○  NoSQL × NoRDB
HandlerSocket plugin  の概要 InnoDB 等のストレージエンジンへの非 SQL インタフェースを提供 TCP/IP でリクエストを受け、ストレージエンジンを直接叩く 独自プロトコルを喋る C++ と Perl のクライアントライブラリを用意 PHP, Java, Python, Ruby, JavaScript(node.js), Scala のライブラリが存在 Linux/FreeBSD/MacOS で動作 Linux に最もチューニングされている BSD ライセンス https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL
構成 mysqld client app Handler Interface Innodb MyISAM Other storage engines … SQL Layer HandlerSocket Plugin Listener for libmysql libmysql libhsclient Applications
ねらい 単純な CRUD 処理を高速に実行したい。 SQL 処理を省略 単純な処理に適用可能な最適化 しかも同じデータを MySQL でも処理できるようにしたい。 単純かつ速度が必要な部分だけを非 SQL に置き換えたい SQL から少しずつ移行したい
参考 :  非 SQL for MySQL (HandlerSocket 以前のもの ) mycached http://developer.cybozu.co.jp/kazuho/2009/08/mycached-memcac.html HandlerSocket と同様に handler インタフェースを叩く memcached プロトコルを喋る NDB API http://dev.mysql.com/doc/ndbapi/en/index.html ndbcluster 専用 HandlerSocket より下の層 ( ストレージエンジン内部 ) を叩く
時系列 2010/03  このころ開発を始める 2010/04  最初のバージョンが完成 2010/06 DeNA Technology Seminar #2  で社外に初めて公開 2010/08 github でソースを公開 2010/08 mobage で本格利用開始
その後の動向 (1) Percona Server に HandlerSocket が取り込まれる Percona Server now both SQL and NOSQL http://www.mysqlperformanceblog.com/2010/12/14/percona-server-now-both-sql-and-nosql/
その後の動向 (2) 2011/04 MySQL Conference & Expo 2011 DeNA 松信が HandlerSocket について講演 DeNA が Corporate Contributor of the Year 2011 を受賞 DeNA is Japan's biggest social game provider and run hundreds of MySQL servers to provide their services. So it is not surprising they also employ some of Japan's best and world famous MySQL experts to work on their LAMP stack. This team produced one of the most interesting innovations MySQL has seen for a while:  HandlerSocket is MySQL's answer to the NoSQL trend, and with a vengeance. With read-transactions now running over 700% faster, it makes MySQL the fastest NoSQL key-value solution out there. And you get best of both worlds: MySQL and NoSQL in the same package. ->  MySQL + HandlerSocket で KVS と同等以上の 性能が出せることを示した
その後の動向 (3) 2011/04 MySQL の memcached インタフェース NoSQL to MySQL with Memcached http ://dev.mysql.com/tech-resources/articles/nosql-to-mysql-with-memcached.html ... The HandlerSocket development at DeNA is a great example of community innovation, with a solution implemented as a custom plug-in and protocol for the MySQL server daemon. ->  MySQL の NoSQL インタフェースが流行?
mobage での利用
mobage への導入 2010/08 mobage で本格利用開始 サービスを停止せずに移行 導入以降トラブルは一度も無し 導入時と同じ mysqld プロセスが動き続けている 一度 HandlerSocket プラグインを更新 mysqld は停止せずにプラグインだけを入れ替え
最初の適用箇所 MySQL + memcached で構成されていた クエリは単純だが数が膨大 既存構成の問題 : 同時接続数の問題で、 mysql の持続接続の利用が難しかった memcached とのデータ同期のための仕組みが複雑で運用に負担がかかっていた ネットワークトラフィックが必要以上に出てしまっていた
導入効果 MySQL と memcached サーバの負荷削減 アプリケーションの CPU 負荷削減 20% ~ 35% 程度削減 ネットワークトラフィックの削減 適用箇所の 70% 程度削減
HandlerSocket の利点
利点 (libmysql と比較して ) CPU を喰わない サーバ側、クライアント側のいずれも効果あり 特に単純なクエリで差が大きい ネットワークトラフィックが減らせる 特に単純なクエリで差が大きい 同時接続数がほぼ無制限 少なくとも 65000 本までは可能 同時接続数を増やしても性能劣化が殆ど無い
HandlerSocket に向いているケース データサイズが十分小さくメモリに乗る 単純なクエリ、サーバの CPU がネック 単純なクエリ、トラフィックがネック 同時接続数が多すぎて持続接続が使えない
HandlerSocket に不向きなケース クエリが複雑で HandlerSocket で実現困難 クエリ一回あたりの CPU 使用量が多く CPU ネック データサイズが大きく Disk IO がネック
機能
HandlerSocket の機能 ( 参照系 ) Primary Key や Unique Key を使った行取得 範囲取得 比較条件に使える演算子は =, >=, >, <=, < SQL の’ IN’ のような複数行取得
HandlerSocket の機能 ( 更新系 ) 参照クエリで得た行の UPDATE と DELETE 行の INSERT トランザクションはサポートしない 更新系クエリは row-based の形式でバイナリログに記録される MySQL のレプリケーション機能を使える 書き込みは durable
実行例 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  を検索
性能
ネックの箇所を見極める テストのネック箇所を見極めないと正確な性能比較ができない サーバの CPU ? クライアントの CPU ? サーバやクライアントのコードの問題? スケーラビリティに問題がある? 例えば Lock contention のせいで CPU を使い切れないなど ネットワーク周り? 帯域の限界に達している? ネットワークドライバがスケーラビリティの問題を抱えていることも
おおよその性能 8 Core HT 付きのサーバ、 1Gb の NIC 一個、 InnoDB 、 adaptive hash index 有効 libmysql:  ~ 100,000 qps CPU が頭打つ HandlerSocket:  ~ 300,000 qps ネットワーク周りがネックになる CPU は頭打たない HandlerSocket(pipelined):  ~ 3,000,000 qps CPU が頭打つ
libmysql との性能比較 ( 参照クエリ ) 単純な参照クエリで数倍~ 10 倍程度 取得する列数が多い場合に特に有効
何故速くなるのか SQL パース処理をしていない ->  CPU 消費が少ない リクエストを集約実行している ->  CPU 消費やディスク IO が少ない 独自プロトコルで通信する ->  ネットワーク消費が少ない
CPU 消費の削減
oprofile – libmysql/mysqld SELECT v from table where k = ?  を大量に実行し、 oprofile で CPU 消費量をしらべる samples|  %| ------------------ 9669940 53.1574 mysqld 4438098 24.3970 vmlinux 1835976 10.0927 libpthread-2.5.so 1680656  9.2389 libc-2.5.so 397970  2.1877 e1000e 89136  0.4900 oprofiled 42881  0.2357 oprofile
oprofile – libmysql/mysqld mysqld 内の CPU 消費 samples  %  symbol name 748022  7.7355  MYSQLparse(void*) 219702  2.2720  my_pthread_fastmutex_lock 205606  2.1262  make_join_statistics(JOIN*, TABLE_LIST*, 198234  2.0500  btr_search_guess_on_hash 180731  1.8690  JOIN::optimize() 177120  1.8317  row_search_for_mysql 171185  1.7703  lex_one_token(void*, void*) 162683  1.6824  alloc_root 131823  1.3632  read_view_open_now 122795  1.2699  mysql_select(THD*, Item***, TABLE_LIST*, 100276  1.0370  open_table(THD*, TABLE_LIST*, st_mem_root*, 99575  1.0297  mem_pool_fill_free_list 96434  0.9973  build_template(row_prebuilt_struct*, THD*, 86349  0.8930  get_hash_symbol(char const*, unsigned int,
oprofile – libmysql/mysqld カーネル内の CPU 消費 samples  %  symbol name 204393  4.6054  schedule 118648  2.6734  tcp_sendmsg 115832  2.6099  tcp_recvmsg 106537  2.4005  tcp_v4_rcv 103915  2.3414  tcp_ack 103534  2.3328  system_call 93864  2.1150  dev_queue_xmit 86831  1.9565  __mod_timer 85891  1.9353  tcp_rcv_established 84083  1.8946  .text.task_rq_lock
oprofile – libmysql/mysqld libmysql/mysqld 使用時の CPU 消費 : mysqld 内で多くの CPU 時間を使用 特に SQL パース処理周辺が CPU 使用 カーネル内ではタスク切り替えに CPU 使用
oprofile – HandlerSocket 先の SQL クエリと同等の処理を HandlerSocket で実行し、 oprofile で CPU 消費量をしらべる samples|  %| ------------------ 1919039 51.0453 vmlinux 811998 21.5987 mysqld 421215 11.2041 libpthread-2.5.so 207166  5.5105 e1000e 191566  5.0955 HandlerSocket.so 188618  5.0171 libc-2.5.so 13622  0.3623 oprofiled 5707  0.1518 oprofile
oprofile – HandlerSocket mysqld 内の CPU 消費 samples  %  symbol name 119684  14.7394  btr_search_guess_on_hash 58202  7.1678  row_search_for_mysql 46946  5.7815  mutex_delay 38617  4.7558  my_pthread_fastmutex_lock 37707  4.6437  buf_page_get_known_nowait 36528  4.4985  rec_get_offsets_func 34625  4.2642  build_template(row_prebuilt_struct*, THD*, TABLE*,  20024  2.4660  row_sel_store_mysql_rec 19347  2.3826  btr_cur_search_to_nth_level 16701  2.0568  row_sel_convert_mysql_key_to_innobase 13343  1.6432  cmp_dtuple_rec_with_match 11381  1.4016  ha_innobase::index_read(unsigned char*,  11176  1.3764  dict_index_copy_types 10762  1.3254  mtr_memo_slot_release 10734  1.3219  ha_innobase::init_table_handle_for_HANDLER()
oprofile – HandlerSocket カーネル内の CPU 消費 samples  %  symbol name 129038  6.7241  tcp_sendmsg 80080  4.1729  tcp_v4_rcv 69658  3.6298  dev_queue_xmit 66171  3.4481  .text.skb_release_data 63316  3.2994  __qdisc_run 60279  3.1411  tcp_recvmsg 59703  3.1111  ip_output 58462  3.0464  .text.skb_release_head_state 48876  2.5469  tcp_ack 48733  2.5394  __alloc_skb 45660  2.3793  ip_queue_xmit 44671  2.3278  tcp_transmit_skb
oprofile – HandlerSocket HandlerSocket 使用時の CPU 消費 : カーネルが最も多く CPU を使用 カーネル内では network 周りで CPU 使用 mysqld 内では innodb の中が使用量多い 特に adaptive hash index 検索処理
並列処理の最適化
並列処理モデル比較 mysqld の並列処理モデル : MySQL 5 では接続あたり 1 スレッド MySQL 6 でスレッドプールもサポート SQL 実行を少数スレッドで実行 メモリ消費の上限が抑えられる
並列処理モデル比較 HandlerSocket の並列処理モデル : 少数のスレッド 各スレッドは複数の接続を処理 既定では epoll 使用 同時接続数は事実上無制限 メモリ消費が少ない
HandlerSocket スレッドの動作 各接続からリクエストを読む DB ロック、 readview 取得 各接続からのリクエストを実行 DB ロック解除 各接続へ結果を返す ここの処理が (1/ 接続数 )  回 程度で済む HandlerSocket の参照系ワーカースレッド の動作
HandlerSocket スレッドの動作 各接続からリクエストを読む DB ロック、トランザクション開始 各接続からのリクエストを実行 コミット、 DB ロック解除 各接続へ結果を返す HandlerSocket の更新系ワーカースレッド の動作 複数のリクエストを一つの トランザクション内で実行
更新処理の性能について 前提 : 同期書き込み (durable) sync_binlog = 1 innodb_flush_log_at_trx_commit  = 1 innodb_support_xa = 1 バッテリ付き write-back cache  又は SSD 性能 : mysql:  ~ 1000 qps innodb plugin  で  sync_binlog = 0  だと group commit が効いてさらに速くなるが、スレーブが追いつかない HandlerSocket:  ~ 30000 qps 書き込みはシリアライズされるので、常にスレーブが追いつく
HandlerSocket の排他制御 MyISAM ならテーブルロックがかかる shared-exclusive lock InnoDB ならテーブルロックはかからない。ただし更新系トランザクションは一度に一つだけ実行されるよう排他制御される。 そうしないとレコードロックを持ち合ってデッドロックするから 更新系スレッドは参照系スレッドをブロックしない HandlerSocket のリクエスト自体はデッドロックフリー そもそも単純なリクエストしかサポートしていないので。
通信の最適化
C/S プロトコル比較 write(3, &quot;L\0\0\0\3select column0,column1,column2,column3,column4 from db_1.table_1 where k=15&quot;, 80) = 80 read(3, &quot;\1\0\0\1\0056\0\0\2\3def\4 db_1 \7 table_1 \7 table_1 \7 column0 \7 column0 \f\r\0<\0\0\0\375\200\0\0\0\0006\0\0\3\3def\4 db_1 \7 table_1 \7 table_1 \7 column1 \7 column1 \f\r\0<\0\0\0\375\200\0\0\0\0006\0\0\4\3def\4 db_1 \7 table_1 \7 table_1 \7 column2 \7 column2 \f\r\0<\0\0\0\375\200\0\0\0\0006\0\0\5\3def\4 db_1 \7 table_1 \7 table_1 \7 column3 \7 column3 \f\r\0<\0\0\0\375\200\0\0\0\0006\0\0\6\3def\4 db_1 \7 table_1 \7 table_1 \7 column4 \7 column4 \f\r\0<\0\0\0\375\200\0\0\0\0\5\0\0\7\376\0\0\&quot;\0\n\0\0\10\001 0 \001 1 \001 2 \001 3 \001 4 \5\0\0\t\376\0\0\&quot;\0&quot;, 16384) = 327 libmysql/mysqld でこのクエリを実行すると… SELECT column0, column1, column2, column3, column4 FROM db_1.table_1 where k = 15
C/S プロトコル比較 write(3, &quot;1\t=\t1\t15\n&quot;, 9)  = 9 read(3, &quot;0\t5\t0\t1\t2\t3\t4\n&quot;, 8192)  = 14 HandlerSocket で同等のクエリを実行すると… 14 bytes 327 bytes response 9 bytes 80 bytes request HandlerSocket libmysql
mysqld/libmysql のプロトコル 結果セットのメタデータが大きい 各列について、 DB 名 、 テーブル名 、 テーブル別名 、 列名 、 列の別名 がメタデータに含まれる http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol#Field_Packet mysql 4.0 までのプロトコルではメタデータが少し小さい。 4.1 以降で大きくなった。 列が多く行が少ないとき相対的に大きい メタデータは結果セットに一つだけ付くから HANDLER クエリでも同様にメタデータが付く server-side prepared statement を使っても同様 プロトコル圧縮を使うと 1/3 程度になる。ただし CPU を喰う。
クライアントライブラリ
libhsclient HandlerSocket 用クライアントライブラリ C++ 低水準インタフェース
DB::HandlerSocket Perl 用クライアントライブラリ xs 経由で libhsclient を呼んでいる my $cli = new DB::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 ], ]);
設定ガイド
HandlerSocket の設定 HandlerSocket_threads = 16 参照系ワーカスレッド数 CPU コア数の 2 倍程度を推奨 HandlerSocket_thread_wr = 1 更新系ワーカスレッド数 増やしても余りメリットなさそう HandlerSocket_port = 9998 参照系ワーカスレッド用ポート HandlerSocket_port_wr = 9999 更新系ワーカスレッド用ポート
その他の設定 innodb_buffer_pool_size を限界まで大きく それでも参照が Disk ネックになるならデータ分割 innodb_log_file_size, innodb_log_files_in_group 大きいとテーブルスペースへの書き戻しが減る 更新系を速くしたいなら限界まで大きく innodb_thread_concurrency = 0 innodb 内の並列度の上限。 0 にすると無効。 open_files_limit = 65535 mysql が開けるファイルディスクリプタ数 HandlerSocket 接続一本あたり 1 つ消費するので大きく
その他の設定 innodb_adaptive_hash_index = 1 B-Tree に加えて Hash 索引を on-demand に付ける機能 完全に Hash に乗れば HandlerSocket 経由の参照が~ 30% 程度速くなる Hash 索引作成中は一時的に参照が遅くなる メモリを喰うのが嫌なら無効にしたほうがよい
durability に関連する設定 sync_binlog = 1 binlog を同期書き込み innodb_flush_log_at_trx_commit = 1 innodb の WAL を同期書き込み innodb_support_xa = 1 内部的に XA を使って binlog と innodb を同期
ベンチマーク
ベンチマーク サーバ Core2Quad Q6600 CentOS 5.4 EXPI9301CT(e1000e) Intel X25-E (write-back cache disabled) クライアントとは 1000base 接続 クライアントのほうが高速のため、全てのワークロードでクライアント側はボトルネックになっていない スキーマ : CREATE TABLE table1 (k varchar(32) KEY, v varchar(32)) engine = INNODB; read テスト : 1000 万レコード SELECT v from table1 where k = ? ランダムアクセスするようキーは乱数で生成 write テスト : 1000 万レコード UPDATE table SET v = ? where k = ? ランダムアクセスするようキーは乱数で生成 binlog 有効 動機的 (durable) 書き込み
スループット
スループット ( 書き込み )
最大レスポンス時間
平均レスポンス時間
今後の予定と課題
課題 ビルドが多少面倒 mysql のソースコードがビルド時に必要 mysql バイナリ互換性問題 mysql のバージョンやビルドオプションの違いによって plugin のバイナリ互換性が無くなる
今後の予定 ドキュメントを書く undocumented な機能が多数存在 不可分な read-modify-write 操作のサポート 一部機能は実装済 InnoDB 以外のエンジンでの検証 クライアントライブラリの整備 スクリプトエンジン orJVM を埋め込む?

More Related Content

What's hot (20)

PDF
配布用Beginnerならきっと役立つmaster slave環境
yut148atgmaildotcom
 
PPTX
MySQL clients
yoku0825
 
PDF
MHA for MySQLとDeNAのオープンソースの話
Yoshinori Matsunobu
 
PDF
MySQLを割と一人で300台管理する技術
yoku0825
 
PDF
MySQLチューニング
yoku0825
 
PDF
MySQL 初めてのチューニング
Craft works
 
PDF
MySQL de NoSQL Fukuoka
Ryusuke Kajiyama
 
PDF
MySQLやSSDとかの話 前編
Takanori Sejima
 
PPTX
MySQLメインの人がPostgreSQLのベンチマークをしてみた話
hiroi10
 
PDF
MySQL日本語利用徹底入門
Mikiya Okuno
 
PDF
DBスキーマもバージョン管理したい!
kwatch
 
PPTX
MySQLの運用でありがちなこと
Hiroaki Sano
 
PPT
MHAを検証して導入した話
Yu Komiya
 
PDF
MySQLバックアップの基本
yoyamasaki
 
PDF
Handlerさんコンニチワ
yoku0825
 
PDF
[B31,32]SQL Server Internal と パフォーマンスチューニング by Yukio Kumazawa
Insight Technology, Inc.
 
PDF
COD2012 C3 : SQL Server 2012で振り返る、SQLOSのスレッド スケジューリング
Masayuki Ozawa
 
PDF
Guide to Cassandra for Production Deployments
smdkk
 
PDF
SQL Server 2014 In Memory OLTP Overview
Masayuki Ozawa
 
PPTX
Cassandraのバックアップと運用を考える
Kazutaka Tomita
 
配布用Beginnerならきっと役立つmaster slave環境
yut148atgmaildotcom
 
MySQL clients
yoku0825
 
MHA for MySQLとDeNAのオープンソースの話
Yoshinori Matsunobu
 
MySQLを割と一人で300台管理する技術
yoku0825
 
MySQLチューニング
yoku0825
 
MySQL 初めてのチューニング
Craft works
 
MySQL de NoSQL Fukuoka
Ryusuke Kajiyama
 
MySQLやSSDとかの話 前編
Takanori Sejima
 
MySQLメインの人がPostgreSQLのベンチマークをしてみた話
hiroi10
 
MySQL日本語利用徹底入門
Mikiya Okuno
 
DBスキーマもバージョン管理したい!
kwatch
 
MySQLの運用でありがちなこと
Hiroaki Sano
 
MHAを検証して導入した話
Yu Komiya
 
MySQLバックアップの基本
yoyamasaki
 
Handlerさんコンニチワ
yoku0825
 
[B31,32]SQL Server Internal と パフォーマンスチューニング by Yukio Kumazawa
Insight Technology, Inc.
 
COD2012 C3 : SQL Server 2012で振り返る、SQLOSのスレッド スケジューリング
Masayuki Ozawa
 
Guide to Cassandra for Production Deployments
smdkk
 
SQL Server 2014 In Memory OLTP Overview
Masayuki Ozawa
 
Cassandraのバックアップと運用を考える
Kazutaka Tomita
 

Similar to Handlersocket 20110517 (20)

PPT
Maatkit で MySQL チューニング
Kensuke Nagae
 
ODP
MySQLのパフォーマンスの話
Tetsuro Ikeda
 
PDF
MySQL Technology Cafe #12 MDS HA検証 ~パラメータからパフォーマンスまで~
オラクルエンジニア通信
 
PDF
hs_spider_hs_something_20110906
Kentoku
 
PDF
DTraceによるMySQL解析ことはじめ
Mikiya Okuno
 
PDF
Enter the-dolphine
Mikiya Okuno
 
PDF
MySQLステータスモニタリング
yoku0825
 
PDF
MySQL 5.5 Update #denatech
Mikiya Okuno
 
PPTX
MySQL5.6と5.7性能比較
hiroi10
 
PDF
LINEのMySQL運用について
LINE Corporation
 
KEY
道具を磨くことのススメ
Kenichi Masuda
 
PPTX
PostgreSQL使いのエンジニアから見たMySQL
toshihiro_kitagawa
 
PPT
Linux/DB Tuning (DevSumi2010, Japanese)
Yoshinori Matsunobu
 
PDF
Maria db
nekogeruge_987
 
PDF
Percona ServerをMySQL 5.6と5.7用に作るエンジニアリング(そしてMongoDBのヒント)
Colin Charles
 
PDF
PHPで大規模ブラウザゲームを開発してわかったこと
Kentaro Matsui
 
PPTX
LINEのMySQL運用について 修正版
LINE Corporation
 
PDF
カジュアルにMySQL Clusterを使ってみよう@MySQL Cluster Casual Talks 2013.09
Mikiya Okuno
 
PDF
MySQL8.0 SYS スキーマ概要
Shinya Sugiyama
 
PDF
node-handlersocket
koichik
 
Maatkit で MySQL チューニング
Kensuke Nagae
 
MySQLのパフォーマンスの話
Tetsuro Ikeda
 
MySQL Technology Cafe #12 MDS HA検証 ~パラメータからパフォーマンスまで~
オラクルエンジニア通信
 
hs_spider_hs_something_20110906
Kentoku
 
DTraceによるMySQL解析ことはじめ
Mikiya Okuno
 
Enter the-dolphine
Mikiya Okuno
 
MySQLステータスモニタリング
yoku0825
 
MySQL 5.5 Update #denatech
Mikiya Okuno
 
MySQL5.6と5.7性能比較
hiroi10
 
LINEのMySQL運用について
LINE Corporation
 
道具を磨くことのススメ
Kenichi Masuda
 
PostgreSQL使いのエンジニアから見たMySQL
toshihiro_kitagawa
 
Linux/DB Tuning (DevSumi2010, Japanese)
Yoshinori Matsunobu
 
Maria db
nekogeruge_987
 
Percona ServerをMySQL 5.6と5.7用に作るエンジニアリング(そしてMongoDBのヒント)
Colin Charles
 
PHPで大規模ブラウザゲームを開発してわかったこと
Kentaro Matsui
 
LINEのMySQL運用について 修正版
LINE Corporation
 
カジュアルにMySQL Clusterを使ってみよう@MySQL Cluster Casual Talks 2013.09
Mikiya Okuno
 
MySQL8.0 SYS スキーマ概要
Shinya Sugiyama
 
node-handlersocket
koichik
 
Ad

Recently uploaded (6)

PDF
VMUG Japan book vsan 20250515 CPU/Memory vSAN
Kazuhiro Sota
 
PDF
20250726_Devinで変えるエンプラシステム開発の未来
Masaki Yamakawa
 
PDF
第三世代 ウェザーステーションキット v3 ー WSC3-L 日本語カタログ
CRI Japan, Inc.
 
PDF
LoRaWAN ウェザーステーションキット v3 -WSC3-L 日本語ユーザーマニュアル
CRI Japan, Inc.
 
PPTX
2025_7_25_吉祥寺_設計ナイト_ADR運用におけるデータ利活用の考え方.pptx
ssuserfcafd1
 
PDF
Google Driveハブ型Obsidian同期環境:PC編集とモバイル閲覧を安全・効率的に実現するクロスデバイス構築ガイド
honeshabri
 
VMUG Japan book vsan 20250515 CPU/Memory vSAN
Kazuhiro Sota
 
20250726_Devinで変えるエンプラシステム開発の未来
Masaki Yamakawa
 
第三世代 ウェザーステーションキット v3 ー WSC3-L 日本語カタログ
CRI Japan, Inc.
 
LoRaWAN ウェザーステーションキット v3 -WSC3-L 日本語ユーザーマニュアル
CRI Japan, Inc.
 
2025_7_25_吉祥寺_設計ナイト_ADR運用におけるデータ利活用の考え方.pptx
ssuserfcafd1
 
Google Driveハブ型Obsidian同期環境:PC編集とモバイル閲覧を安全・効率的に実現するクロスデバイス構築ガイド
honeshabri
 
Ad

Handlersocket 20110517

  • 1. HandlerSocket plugin for MySQL 2011/05/17 NoSQL セミナー @ 渋谷 株式会社 DeNA システム統括本部 IT 基盤部 樋口 証 <higuchi dot akira at dena dot jp>
  • 3. HandlerSocket plugin とは MySQL の非 SQL なインタフェース ○ NoSQL × NoRDB
  • 4. HandlerSocket plugin の概要 InnoDB 等のストレージエンジンへの非 SQL インタフェースを提供 TCP/IP でリクエストを受け、ストレージエンジンを直接叩く 独自プロトコルを喋る C++ と Perl のクライアントライブラリを用意 PHP, Java, Python, Ruby, JavaScript(node.js), Scala のライブラリが存在 Linux/FreeBSD/MacOS で動作 Linux に最もチューニングされている BSD ライセンス https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL
  • 5. 構成 mysqld client app Handler Interface Innodb MyISAM Other storage engines … SQL Layer HandlerSocket Plugin Listener for libmysql libmysql libhsclient Applications
  • 6. ねらい 単純な CRUD 処理を高速に実行したい。 SQL 処理を省略 単純な処理に適用可能な最適化 しかも同じデータを MySQL でも処理できるようにしたい。 単純かつ速度が必要な部分だけを非 SQL に置き換えたい SQL から少しずつ移行したい
  • 7. 参考 : 非 SQL for MySQL (HandlerSocket 以前のもの ) mycached http://developer.cybozu.co.jp/kazuho/2009/08/mycached-memcac.html HandlerSocket と同様に handler インタフェースを叩く memcached プロトコルを喋る NDB API http://dev.mysql.com/doc/ndbapi/en/index.html ndbcluster 専用 HandlerSocket より下の層 ( ストレージエンジン内部 ) を叩く
  • 8. 時系列 2010/03 このころ開発を始める 2010/04 最初のバージョンが完成 2010/06 DeNA Technology Seminar #2 で社外に初めて公開 2010/08 github でソースを公開 2010/08 mobage で本格利用開始
  • 9. その後の動向 (1) Percona Server に HandlerSocket が取り込まれる Percona Server now both SQL and NOSQL http://www.mysqlperformanceblog.com/2010/12/14/percona-server-now-both-sql-and-nosql/
  • 10. その後の動向 (2) 2011/04 MySQL Conference & Expo 2011 DeNA 松信が HandlerSocket について講演 DeNA が Corporate Contributor of the Year 2011 を受賞 DeNA is Japan's biggest social game provider and run hundreds of MySQL servers to provide their services. So it is not surprising they also employ some of Japan's best and world famous MySQL experts to work on their LAMP stack. This team produced one of the most interesting innovations MySQL has seen for a while: HandlerSocket is MySQL's answer to the NoSQL trend, and with a vengeance. With read-transactions now running over 700% faster, it makes MySQL the fastest NoSQL key-value solution out there. And you get best of both worlds: MySQL and NoSQL in the same package. -> MySQL + HandlerSocket で KVS と同等以上の 性能が出せることを示した
  • 11. その後の動向 (3) 2011/04 MySQL の memcached インタフェース NoSQL to MySQL with Memcached http ://dev.mysql.com/tech-resources/articles/nosql-to-mysql-with-memcached.html ... The HandlerSocket development at DeNA is a great example of community innovation, with a solution implemented as a custom plug-in and protocol for the MySQL server daemon. -> MySQL の NoSQL インタフェースが流行?
  • 13. mobage への導入 2010/08 mobage で本格利用開始 サービスを停止せずに移行 導入以降トラブルは一度も無し 導入時と同じ mysqld プロセスが動き続けている 一度 HandlerSocket プラグインを更新 mysqld は停止せずにプラグインだけを入れ替え
  • 14. 最初の適用箇所 MySQL + memcached で構成されていた クエリは単純だが数が膨大 既存構成の問題 : 同時接続数の問題で、 mysql の持続接続の利用が難しかった memcached とのデータ同期のための仕組みが複雑で運用に負担がかかっていた ネットワークトラフィックが必要以上に出てしまっていた
  • 15. 導入効果 MySQL と memcached サーバの負荷削減 アプリケーションの CPU 負荷削減 20% ~ 35% 程度削減 ネットワークトラフィックの削減 適用箇所の 70% 程度削減
  • 17. 利点 (libmysql と比較して ) CPU を喰わない サーバ側、クライアント側のいずれも効果あり 特に単純なクエリで差が大きい ネットワークトラフィックが減らせる 特に単純なクエリで差が大きい 同時接続数がほぼ無制限 少なくとも 65000 本までは可能 同時接続数を増やしても性能劣化が殆ど無い
  • 18. HandlerSocket に向いているケース データサイズが十分小さくメモリに乗る 単純なクエリ、サーバの CPU がネック 単純なクエリ、トラフィックがネック 同時接続数が多すぎて持続接続が使えない
  • 19. HandlerSocket に不向きなケース クエリが複雑で HandlerSocket で実現困難 クエリ一回あたりの CPU 使用量が多く CPU ネック データサイズが大きく Disk IO がネック
  • 21. HandlerSocket の機能 ( 参照系 ) Primary Key や Unique Key を使った行取得 範囲取得 比較条件に使える演算子は =, >=, >, <=, < SQL の’ IN’ のような複数行取得
  • 22. HandlerSocket の機能 ( 更新系 ) 参照クエリで得た行の UPDATE と DELETE 行の INSERT トランザクションはサポートしない 更新系クエリは row-based の形式でバイナリログに記録される MySQL のレプリケーション機能を使える 書き込みは durable
  • 23. 実行例 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 を検索
  • 25. ネックの箇所を見極める テストのネック箇所を見極めないと正確な性能比較ができない サーバの CPU ? クライアントの CPU ? サーバやクライアントのコードの問題? スケーラビリティに問題がある? 例えば Lock contention のせいで CPU を使い切れないなど ネットワーク周り? 帯域の限界に達している? ネットワークドライバがスケーラビリティの問題を抱えていることも
  • 26. おおよその性能 8 Core HT 付きのサーバ、 1Gb の NIC 一個、 InnoDB 、 adaptive hash index 有効 libmysql: ~ 100,000 qps CPU が頭打つ HandlerSocket: ~ 300,000 qps ネットワーク周りがネックになる CPU は頭打たない HandlerSocket(pipelined): ~ 3,000,000 qps CPU が頭打つ
  • 27. libmysql との性能比較 ( 参照クエリ ) 単純な参照クエリで数倍~ 10 倍程度 取得する列数が多い場合に特に有効
  • 28. 何故速くなるのか SQL パース処理をしていない -> CPU 消費が少ない リクエストを集約実行している -> CPU 消費やディスク IO が少ない 独自プロトコルで通信する -> ネットワーク消費が少ない
  • 30. oprofile – libmysql/mysqld SELECT v from table where k = ?  を大量に実行し、 oprofile で CPU 消費量をしらべる samples| %| ------------------ 9669940 53.1574 mysqld 4438098 24.3970 vmlinux 1835976 10.0927 libpthread-2.5.so 1680656 9.2389 libc-2.5.so 397970 2.1877 e1000e 89136 0.4900 oprofiled 42881 0.2357 oprofile
  • 31. oprofile – libmysql/mysqld mysqld 内の CPU 消費 samples % symbol name 748022 7.7355 MYSQLparse(void*) 219702 2.2720 my_pthread_fastmutex_lock 205606 2.1262 make_join_statistics(JOIN*, TABLE_LIST*, 198234 2.0500 btr_search_guess_on_hash 180731 1.8690 JOIN::optimize() 177120 1.8317 row_search_for_mysql 171185 1.7703 lex_one_token(void*, void*) 162683 1.6824 alloc_root 131823 1.3632 read_view_open_now 122795 1.2699 mysql_select(THD*, Item***, TABLE_LIST*, 100276 1.0370 open_table(THD*, TABLE_LIST*, st_mem_root*, 99575 1.0297 mem_pool_fill_free_list 96434 0.9973 build_template(row_prebuilt_struct*, THD*, 86349 0.8930 get_hash_symbol(char const*, unsigned int,
  • 32. oprofile – libmysql/mysqld カーネル内の CPU 消費 samples % symbol name 204393 4.6054 schedule 118648 2.6734 tcp_sendmsg 115832 2.6099 tcp_recvmsg 106537 2.4005 tcp_v4_rcv 103915 2.3414 tcp_ack 103534 2.3328 system_call 93864 2.1150 dev_queue_xmit 86831 1.9565 __mod_timer 85891 1.9353 tcp_rcv_established 84083 1.8946 .text.task_rq_lock
  • 33. oprofile – libmysql/mysqld libmysql/mysqld 使用時の CPU 消費 : mysqld 内で多くの CPU 時間を使用 特に SQL パース処理周辺が CPU 使用 カーネル内ではタスク切り替えに CPU 使用
  • 34. oprofile – HandlerSocket 先の SQL クエリと同等の処理を HandlerSocket で実行し、 oprofile で CPU 消費量をしらべる samples| %| ------------------ 1919039 51.0453 vmlinux 811998 21.5987 mysqld 421215 11.2041 libpthread-2.5.so 207166 5.5105 e1000e 191566 5.0955 HandlerSocket.so 188618 5.0171 libc-2.5.so 13622 0.3623 oprofiled 5707 0.1518 oprofile
  • 35. oprofile – HandlerSocket mysqld 内の CPU 消費 samples % symbol name 119684 14.7394 btr_search_guess_on_hash 58202 7.1678 row_search_for_mysql 46946 5.7815 mutex_delay 38617 4.7558 my_pthread_fastmutex_lock 37707 4.6437 buf_page_get_known_nowait 36528 4.4985 rec_get_offsets_func 34625 4.2642 build_template(row_prebuilt_struct*, THD*, TABLE*, 20024 2.4660 row_sel_store_mysql_rec 19347 2.3826 btr_cur_search_to_nth_level 16701 2.0568 row_sel_convert_mysql_key_to_innobase 13343 1.6432 cmp_dtuple_rec_with_match 11381 1.4016 ha_innobase::index_read(unsigned char*, 11176 1.3764 dict_index_copy_types 10762 1.3254 mtr_memo_slot_release 10734 1.3219 ha_innobase::init_table_handle_for_HANDLER()
  • 36. oprofile – HandlerSocket カーネル内の CPU 消費 samples % symbol name 129038 6.7241 tcp_sendmsg 80080 4.1729 tcp_v4_rcv 69658 3.6298 dev_queue_xmit 66171 3.4481 .text.skb_release_data 63316 3.2994 __qdisc_run 60279 3.1411 tcp_recvmsg 59703 3.1111 ip_output 58462 3.0464 .text.skb_release_head_state 48876 2.5469 tcp_ack 48733 2.5394 __alloc_skb 45660 2.3793 ip_queue_xmit 44671 2.3278 tcp_transmit_skb
  • 37. oprofile – HandlerSocket HandlerSocket 使用時の CPU 消費 : カーネルが最も多く CPU を使用 カーネル内では network 周りで CPU 使用 mysqld 内では innodb の中が使用量多い 特に adaptive hash index 検索処理
  • 39. 並列処理モデル比較 mysqld の並列処理モデル : MySQL 5 では接続あたり 1 スレッド MySQL 6 でスレッドプールもサポート SQL 実行を少数スレッドで実行 メモリ消費の上限が抑えられる
  • 40. 並列処理モデル比較 HandlerSocket の並列処理モデル : 少数のスレッド 各スレッドは複数の接続を処理 既定では epoll 使用 同時接続数は事実上無制限 メモリ消費が少ない
  • 41. HandlerSocket スレッドの動作 各接続からリクエストを読む DB ロック、 readview 取得 各接続からのリクエストを実行 DB ロック解除 各接続へ結果を返す ここの処理が (1/ 接続数 ) 回 程度で済む HandlerSocket の参照系ワーカースレッド の動作
  • 42. HandlerSocket スレッドの動作 各接続からリクエストを読む DB ロック、トランザクション開始 各接続からのリクエストを実行 コミット、 DB ロック解除 各接続へ結果を返す HandlerSocket の更新系ワーカースレッド の動作 複数のリクエストを一つの トランザクション内で実行
  • 43. 更新処理の性能について 前提 : 同期書き込み (durable) sync_binlog = 1 innodb_flush_log_at_trx_commit = 1 innodb_support_xa = 1 バッテリ付き write-back cache 又は SSD 性能 : mysql: ~ 1000 qps innodb plugin で sync_binlog = 0 だと group commit が効いてさらに速くなるが、スレーブが追いつかない HandlerSocket: ~ 30000 qps 書き込みはシリアライズされるので、常にスレーブが追いつく
  • 44. HandlerSocket の排他制御 MyISAM ならテーブルロックがかかる shared-exclusive lock InnoDB ならテーブルロックはかからない。ただし更新系トランザクションは一度に一つだけ実行されるよう排他制御される。 そうしないとレコードロックを持ち合ってデッドロックするから 更新系スレッドは参照系スレッドをブロックしない HandlerSocket のリクエスト自体はデッドロックフリー そもそも単純なリクエストしかサポートしていないので。
  • 46. C/S プロトコル比較 write(3, &quot;L\0\0\0\3select column0,column1,column2,column3,column4 from db_1.table_1 where k=15&quot;, 80) = 80 read(3, &quot;\1\0\0\1\0056\0\0\2\3def\4 db_1 \7 table_1 \7 table_1 \7 column0 \7 column0 \f\r\0<\0\0\0\375\200\0\0\0\0006\0\0\3\3def\4 db_1 \7 table_1 \7 table_1 \7 column1 \7 column1 \f\r\0<\0\0\0\375\200\0\0\0\0006\0\0\4\3def\4 db_1 \7 table_1 \7 table_1 \7 column2 \7 column2 \f\r\0<\0\0\0\375\200\0\0\0\0006\0\0\5\3def\4 db_1 \7 table_1 \7 table_1 \7 column3 \7 column3 \f\r\0<\0\0\0\375\200\0\0\0\0006\0\0\6\3def\4 db_1 \7 table_1 \7 table_1 \7 column4 \7 column4 \f\r\0<\0\0\0\375\200\0\0\0\0\5\0\0\7\376\0\0\&quot;\0\n\0\0\10\001 0 \001 1 \001 2 \001 3 \001 4 \5\0\0\t\376\0\0\&quot;\0&quot;, 16384) = 327 libmysql/mysqld でこのクエリを実行すると… SELECT column0, column1, column2, column3, column4 FROM db_1.table_1 where k = 15
  • 47. C/S プロトコル比較 write(3, &quot;1\t=\t1\t15\n&quot;, 9) = 9 read(3, &quot;0\t5\t0\t1\t2\t3\t4\n&quot;, 8192) = 14 HandlerSocket で同等のクエリを実行すると… 14 bytes 327 bytes response 9 bytes 80 bytes request HandlerSocket libmysql
  • 48. mysqld/libmysql のプロトコル 結果セットのメタデータが大きい 各列について、 DB 名 、 テーブル名 、 テーブル別名 、 列名 、 列の別名 がメタデータに含まれる http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol#Field_Packet mysql 4.0 までのプロトコルではメタデータが少し小さい。 4.1 以降で大きくなった。 列が多く行が少ないとき相対的に大きい メタデータは結果セットに一つだけ付くから HANDLER クエリでも同様にメタデータが付く server-side prepared statement を使っても同様 プロトコル圧縮を使うと 1/3 程度になる。ただし CPU を喰う。
  • 51. DB::HandlerSocket Perl 用クライアントライブラリ xs 経由で libhsclient を呼んでいる my $cli = new DB::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 ], ]);
  • 53. HandlerSocket の設定 HandlerSocket_threads = 16 参照系ワーカスレッド数 CPU コア数の 2 倍程度を推奨 HandlerSocket_thread_wr = 1 更新系ワーカスレッド数 増やしても余りメリットなさそう HandlerSocket_port = 9998 参照系ワーカスレッド用ポート HandlerSocket_port_wr = 9999 更新系ワーカスレッド用ポート
  • 54. その他の設定 innodb_buffer_pool_size を限界まで大きく それでも参照が Disk ネックになるならデータ分割 innodb_log_file_size, innodb_log_files_in_group 大きいとテーブルスペースへの書き戻しが減る 更新系を速くしたいなら限界まで大きく innodb_thread_concurrency = 0 innodb 内の並列度の上限。 0 にすると無効。 open_files_limit = 65535 mysql が開けるファイルディスクリプタ数 HandlerSocket 接続一本あたり 1 つ消費するので大きく
  • 55. その他の設定 innodb_adaptive_hash_index = 1 B-Tree に加えて Hash 索引を on-demand に付ける機能 完全に Hash に乗れば HandlerSocket 経由の参照が~ 30% 程度速くなる Hash 索引作成中は一時的に参照が遅くなる メモリを喰うのが嫌なら無効にしたほうがよい
  • 56. durability に関連する設定 sync_binlog = 1 binlog を同期書き込み innodb_flush_log_at_trx_commit = 1 innodb の WAL を同期書き込み innodb_support_xa = 1 内部的に XA を使って binlog と innodb を同期
  • 58. ベンチマーク サーバ Core2Quad Q6600 CentOS 5.4 EXPI9301CT(e1000e) Intel X25-E (write-back cache disabled) クライアントとは 1000base 接続 クライアントのほうが高速のため、全てのワークロードでクライアント側はボトルネックになっていない スキーマ : CREATE TABLE table1 (k varchar(32) KEY, v varchar(32)) engine = INNODB; read テスト : 1000 万レコード SELECT v from table1 where k = ? ランダムアクセスするようキーは乱数で生成 write テスト : 1000 万レコード UPDATE table SET v = ? where k = ? ランダムアクセスするようキーは乱数で生成 binlog 有効 動機的 (durable) 書き込み
  • 64. 課題 ビルドが多少面倒 mysql のソースコードがビルド時に必要 mysql バイナリ互換性問題 mysql のバージョンやビルドオプションの違いによって plugin のバイナリ互換性が無くなる
  • 65. 今後の予定 ドキュメントを書く undocumented な機能が多数存在 不可分な read-modify-write 操作のサポート 一部機能は実装済 InnoDB 以外のエンジンでの検証 クライアントライブラリの整備 スクリプトエンジン orJVM を埋め込む?