Weitere ähnliche Inhalte Ähnlich wie MySQL Binlog Events でストリーム処理してみた #MySQLUC15 (20) Mehr von Yahoo!デベロッパーネットワーク (20) Kürzlich hochgeladen (12) MySQL Binlog Events でストリーム処理してみた #MySQLUC152. 自己紹介
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
2
• 三谷 智史(@mita2)
• 所属
ヤフー(株)
DBMS技術
• RDB専門部隊 13名
• DB Administration 黒帯
3. 本日の流れ
1. Yahoo JAPAN! のMySQL 利用状況
2. ストリーム処理の利点
3. Binlog Events を検証してみた
1. サンプルコード解説
2. 更新内容を取り出す方法
3. ありそうで、なかった機能
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
3
4. 本日の流れ
1. Yahoo JAPAN! のMySQL 利用状況
2. ストリーム処理の利点
3. Binlog Events を検証してみた
1. サンプルコード解説
2. 更新内容を取り出す方法
3. ありそうで、なかった機能
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
4
7. サーバ台数
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
7
• 約220台
• オンプレです
• 容量18TB
• ※ マスターのみカウント
マスター
サーバ
スレーブ
サーバ
バックアップ用
スレーブ
サーバ構成比率
9. 共有ストレージのHAです
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
9
• 複数MySQLを集約
• 商用ストレージ
• 詳細:
「レプリケーションを使わない」
でWEB検索
Oracle Clusterware
使ってます
Oracle Clusterware
使ってます
10. 世間で実績の少なそうな?機能の実績
• 5.6 + GTID
• 100DB以上で動かしてますが問題ないです
• パーティション
• 20DB以上で採用
• DROP PARITTIONによる高速データ削除
• ALTERに問題あり、使うなら5.6から… (Bug 77318)
• InnoDBテーブル 圧縮
• 20DB以上で採用。READ IO減ってかなりGOOD。
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
10
11. We love MySQL
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
11
0
100
200
300
400
500
600
We Love
12. 本日の流れ
1. Yahoo JAPAN! のMySQL 利用状況
2. ストリーム処理の利点
3. Binlog Events を検証してみた
1. サンプルコード解説
2. 更新内容を取り出す方法
3. ありそうで、なかった機能
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
12
13. Yahoo! におけるストリーム処理
13
• 設立初期からストリーム処理を活用
• fluentd的なミドルウェア
決済システム
購入処理購入処理
Log
Reader
Log
Reader
Log
Consumer
Log
Consumer
Log
Consumer
Log
Consumer
トランザク
ションログ
トランザク
ションログ
ECサービス
システム
ストレージサービス
システム
キャンペーン
フラグON
容量増量
フラグON
プレミアム
会員購入 非同期転送
処理イメージ、実際とは異なります
15. 1.スケールアウト
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
15
スケールアウトしやすいスケールアウトしやすい
決済システム
購入処理購入処理
Log
Reader1
Log
Reader1
Log
Consumer2
Log
Consumer2
Log
Consumer1
Log
Consumer1
トランザク
ションログ
トランザク
ションログ
ECサービス
システム
キャンペーン
フラグON
Log
Reader2
Log
Reader2
ユーザIDで
分散
ユーザIDで
分散
16. 2.連携先の影響を受けにくい
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
16
連携先の影響を受けにくい連携先の影響を受けにくい
決済システム
購入処理購入処理
Log
Reader
Log
Reader
Log
Consumer
Log
Consumer
Log
Consumer
Log
Consumer
トランザク
ションログ
トランザク
ションログ
ECサービス
システム
ストレージサービス
システム
キャンペーン
フラグON
容量増量
フラグON
非同期転送
DOWNDOWN
18. ☆ チン マチクタビレタ~
マチクタビレタ~
☆ チン 〃 ∧_∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
ヽ ___\(\・∀・) < MySQLでストリーム処理まだ~
\_/⊂ ⊂_ ) \_____________
/ ̄ ̄ ̄ ̄ ̄ ̄ /|
| ̄ ̄ ̄ ̄ ̄ ̄ ̄| |
| 愛媛みかん |/
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
18
(社内の声)
19. 本日の流れ
1. Yahoo JAPAN! のMySQL 利用事例
2. ストリーム処理の利点
3. Binlog Events を検証してみた
1. サンプルコード解説
2. 更新内容を取り出す方法
3. ありそうで、なかった機能
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
19
20. MySQL Binlog Events
• バイナリログを用いたストリーム処理ができる
• MySQL Labs で公開中(2015/12現在)
• 昔はBinlog APIっていうやつがあったらしい
• C++ libraries
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
20
21. 利用イメージ
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
21
決済システム
購入処理購入処理
BinlogEvents
を使ったプログラム
BinlogEvents
を使ったプログラム
バイナリログバイナリログ
ECサービス
システム
ストレージサービス
システム
キャンペーン
フラグON
容量増量
フラグON
非同期転送
処理イメージ
• さっきの例だとこう
BinlogEvents
を使ったプログラム
BinlogEvents
を使ったプログラム
23. Binlog Eventsのビルド
• Labs から mysql-binlog-events-1.0.1-src.tar.gz をDL
• サンプルが同梱されてます
• mysql-devel パッケージだけではビルド不可
• MySQL5.7 のソースもダウンロードしましょう
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
23
$ cmake -DMYSQLCLIENT_STATIC_LINKING:BOOL=TRUE ¥
-DMYSQL_DIR=/usr/bin ¥
-DMYSQL_SOURCE_INCLUDE_DIR=<ソース置いた場所>/include ¥
-DENABLE_DOWNLOADS=1 .
$ make
$ cd example
$ make
25. CHANGE LOG
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
25
############################
ChangeLog for Binary Log API
############################
Release 0.1.0 (released April 20, 2013)
---------------------------------------
* BAPI-1: In the binlog-replication-listener library,
mysql::Binary_log::connect function does not abort when
non-existent file name or server is provided
29. basic-1 のソース - 接続方法
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
29
Binary_log_driver *drv= create_transport(argv[1]);
if (drv == NULL)
return 1;
Binary_log binlog(drv);
if (binlog.connect() != ERR_OK)
{
delete drv;
return 1;
}
URIを渡して接続URIを渡して接続
30. basic-1 を動かしてみる
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
30
$ ./basic-1 mysql://root:Password123_@localhost:3306
Found event of type 2
Found event of type 19
Found event of type 30
mysql> CREATE TABLE `mytable` ~
mysql> INSERT INTO mytable (v1) VALUES('abc');
31. イベントとは
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
31
QueryQuery BEGINBEGIN
Table_MapTable_Map 処理する対象テーブルの指定処理する対象テーブルの指定
Write_rowsWrite_rows INSERT INTO ~INSERT INTO ~
Update_rowsUpdate_rows UPDATE ~UPDATE ~
• 1つのトランザクションは複数イベントで構成
• 「Table_Map」や「Rotate」など特殊なイベン
トもある
イベントタイプ イベント内容(イメージ)
トランザクション
POS
POS
POS
POS
34. basic-2 を動かしてみる
• SQLが表示される・・・?
• basic-2 はバグってます
• 本当は 変数 を値に置換してSQLを表示する
プログラムです
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
34
$ ./basic-2 mysql://root:Password123_@localhost:3306
create table mytable (pk serial, v1 varchar(255))
BEGIN
insert into mytable (v1) values(@myvar) 置換されてない置換されてない
36. basic-2 を動かしてみる(修正ver)
• binlog_format=STATEMENTで動かしましょう
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
36
$ ./basic-2 mysql://root:Password123_@localhost:3306
create database hogex
create table mytable (pk serial, v1 varchar(255))
insert into mytable (v1) values(123) @myvarが置換される@myvarが置換される
mysql> CREATE TABLE mytable (pk SERIAL, v1 VARCHAR(5));
mysql> SET @myvar=“123”;
mysql> INSERT INTO mytable (v1) VALUES(@myvar);
38. basic-2 のソース - main
Map variables;
Save_variables<Map> save_variables(variables);
Content_stream_handler handler;
handler.add_listener(save_variables);
Replace_variables<Map> replace_variables(variables);
handler.add_listener(replace_variables);
<snip>
while (true)
{
int error_number;
error_number= drv->get_next_event(&buf_and_len);
<snip>
handler.handle_event(&event);
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
38
ハンドラーを生成ハンドラーを生成
ハンドラーを登録ハンドラーを登録
バイナリログから
イベントを読み取る
バイナリログから
イベントを読み取る
登録したハンドラーに
イベントを渡してを処理
登録したハンドラーに
イベントを渡してを処理
ループループ
39. Binlog Events の設計思想
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
39
Get_next_eventGet_next_event
ループループ
ループ
コンテンツハンドラ
(クラス)
コンテンツハンドラ
(クラス)
- process_event(Delete_rows)
- process_event(Write_rows)
- process_event(Delete_rows)
- process_event(Write_rows)
コンテンツハンドラコンテンツハンドラ
コンテンツハンドラコンテンツハンドラ
• 1イベントごとにハンドラで定義し
たprocess_eventが呼び出される
• イベントタイプごとに処理したい内
容をコーディングする
• コンテンツハンドラは複数設定可能
INSERTされたとき
に実施したい処理を
書く
INSERTされたとき
に実施したい処理を
書く
40. Save_variablesコンテンツハンドラ
template <class AssociativeContainer>
class Save_variables : public Content_handler {
Binary_log_event *process_event(User_var_event *event) {
std::string a(event->val, 0, event->val_len);
m_var[event->name] = a;
return event;
}
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
40
変数のSETイベント
を受け入れる
例)SET @abc = 123
変数のSETイベント
を受け入れる
例)SET @abc = 123
val には値(123)が
入ってる
val には値(123)が
入ってる
グローバル変数のハッシュに
登録しておく
例)m_var[abc] = 123
グローバル変数のハッシュに
登録しておく
例)m_var[abc] = 123
41. Replace_variablesコンテンツハンドラ
Binary_log_event *process_event(Query_event *event) {
std::string query = event->query;
size_t start, end = 0;
while (true) {
start = query.find_first_of("@", end);
if (start == std::string::npos)
break;
end = query.find_first_not_of("abcdefghijklmnopqrstuvwxyz", start+1);
std::string key = query.substr(start + 1, end - start - 1);
query.replace(start, end - start, "'" + m_var[key] + "'");
}
event->query= query.c_str();
return event;
}
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
41
クエリから@を探すクエリから@を探す
@に続く英字の位置を検索@に続く英字の位置を検索
@~ を置換@~ を置換
クエリに対する
イベントのみ処理する
クエリに対する
イベントのみ処理する
Save_variablesで
保存しておいたもの
Save_variablesで
保存しておいたもの
43. binlog-browser
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
43
$ ./binlog-browser mysql://root:Password123_@localhost:3306
Start Position End Position Event Length Event Type
219 344 125 Query[2]
Event Info: use `hoge`; create table mytable (pk serial, v1 varchar(255))
344 409 65 Anonymous_Gtid[34]
Event Info:
409 482 73 Query[2]
Event Info: BEGIN
482 536 54 Table_map[19]
Event Info: table id: 109 (hogex.mytable)
536 584 48 Write_rows[30]
Event Info: table id: 109 flags: Last event of the statement
584 615 31 Xid[16]
Event Info: Xid ID=26
44. binlog-browser のソース
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
44
Binary_log_driver *drv= create_transport(uri.c_str());
Binary_log binlog(drv);
int error_number= binlog.connect();
if (const char* msg= str_error(error_number))
cerr << msg << endl;
<snip>
if (binlog.set_position(opt_start_pos) != ERR_OK)
{
cerr << "The specified position "
<< opt_start_pos
<< " cannot be set"
<< endl;
return 1;
}
引数で指定したポジション
にジャンプ
引数で指定したポジション
にジャンプ
48. カラムの値をとるコード
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
48
Binary_log_event *process_event(binary_log::Rows_event *event) {
Int2event_map::iterator ti_it= m_table_index.find(event->get_table_id());
binary_log::Row_event_set rows(event, ti_it->second);
binary_log::Row_of_fields fields= *row_it;
if (event->get_event_type() == binary_log::WRITE_ROWS_EVENT ||
event->get_event_type() == binary_log::WRITE_ROWS_EVENT_V1) {
std::cout << event_start_pos << "¥tINSERT¥t" <<
ti_it->second->m_dbnam << "." << ti_it->second->m_tblnam << "¥t";
binary_log::Row_of_fields::iterator field_it= fields.begin();
binary_log::Converter converter;
if (field_it != fields.end()) {
do {
std::string str;
converter.to(str, *field_it);
std::cout << str << "¥t";
} while (++field_it != fields.end());
ROWモードの
イベントを受け取る
ROWモードの
イベントを受け取る
INSERTの場合INSERTの場合
バイナリをデコードバイナリをデコード
直前のTable_Map
イベントからテーブル情報を
取得
直前のTable_Map
イベントからテーブル情報を
取得
49. 実行例
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
49
$ ./decode mysql://root:Password123_@localhost:3306
1401 INSERT t.mytable 1 123
1664 UPDATE t.mytable 1 123 1 456
1941 DELETE t.mytable 1 456
mysql> INSERT INTO mytable VALUES(1, "123");
mysql> UPDATE mytable SET c1 = "456";
mysql> DELETE mytable WHERE pk = 1;
51. サーバのbinlog_formatはROWで
• binlog_format=ROW
• タイプ Rows_event で記録
• 変更内容がバイナリで記録されている
• バイナリから実際の値にデコードする関数がある
• binlog eventsを使うにはこちらが前提
• binlog_format=STATEMENT
• タイプ Query_event で記録
• SQLがそのままバイナリログに記載される
• SQLから変更内容を特定するのは困難、Binlog
Events を使う場合は使わない想定
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
51
52. binlog_image にも注意
• binlog_image=full
• デフォルト
• 変更された行のPKと、その行の内容を記録
• binlog_image=minimal
• 更新を再現するのに最小限の情報のみを記録
• バイナリログのサイズが小さくて済む
• 例)DELETEだとPKのみ
• Binlog Events でPKしか拾えなくなるので注意
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
52
54. ありそうで、なかった機能 その1
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
54
分散、ルーティングの仕組み分散、ルーティングの仕組み
Binlog
Events
Binlog
Events
バイナリログバイナリログ
ユーザID: 1-1000を担当
するサーバ
Binlog
Events
Binlog
Events
ユーザID: 1000-2000を担当
するサーバ
関係ないログは
読み飛ばす実装
が必要
関係ないログは
読み飛ばす実装
が必要
55. ありそうで、なかった機能 その2
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
55
「どこまで処理したか」を記録しておく仕組み「どこまで処理したか」を記録しておく仕組み
• 「BEGIN」イベントが来たら、それまでのバイ
ナリログ、ログポジションをファイルに書く
• 再開時、ファイルを読んで、そこまで読み飛ばす
57. まとめ
Copyright (C) 2015 Yahoo Japan Corporation. All Rights Reserved. 無断引用・転載禁止
57
C++つらいC++つらい
なんとかストリーム処理できそうですなんとかストリーム処理できそうです
LLラッパーを一緒に書いてくれる人募集LLラッパーを一緒に書いてくれる人募集