Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

DB Tech showcase Tokyo 2015 Works Applications

7,839 views

Published on

DB Tech showcase Tokyo 2015
にて発表した資料です。

Published in: Technology
  • Be the first to comment

DB Tech showcase Tokyo 2015 Works Applications

  1. 1. RDB完全脱却!OracleからCassandra, Sparkへのリプレース実践例 2015年6月12日 株式会社ワークスアプリケーションズ ATE本部 HUE Backendチーム 堤 勇人
  2. 2. 2 堤 勇人 Tsutsumi Hayato 株式会社ワークスアプリケーションズ アドバンスドテクノロジアンドエンジニアリング本部 HUE Backend チーム リーダー HUEにてシステム全体のアーキテクチャから、 個々の要素技術開発まで担当 @2t3
  3. 3. 3 本日の内容でない物 ✗ RDBはもういらない ✗ 全部分散処理しよう ✗ ビッグデータ ✗ Cassandraの詳細解説 ✗ 弊社新製品の機能紹介
  4. 4. 4 本日の内容 Oracleに完全依存したパッケージソフトウェアを、 Cassandra, Elasticsearch等の分散データベースで 置き換えてみる。
  5. 5. 5 アジェンダ 1.Oracleに完全依存したソフトウェア 2.KVSで置き換える 3.リプレースしたメリット・デメリット 4.まとめ
  6. 6. 6 1.Oracleに完全依存したソフトウェア
  7. 7. 7 select bd0.otr_id FROM corp_hst crp, section_hst sec, class_hst cls, post_hst pst, office_hst ofc, position_hst psn, speciality_hst spc, costitem_hst cst, charge _hst cr g, extr a_hst ex01, extra_hst ex02, extra_hst ex03, extra_hst ex04, extra_hst ex05, extra_hst ex06, extra_hst ex07, extra_hst ex08, extra_hst ex09, extra_hst ex10, corp_hst ocrp, section_hst osec, rank_hst rnk, jobgrade_hst jobg, (SELECT hd.otr_id, hd.anc_date, bd.* FROM asnhst_hd hd, asnhst_mainbd bd WHERE hd. hst_id = bd. hst_id) bd0, asnhst_employ bd1, asnhst_absence bd2, (SELECT hd. otr_id, hd.an c_date as hd_anc_date, tp.* FROM asnhst_hd hd, asnhst_temp_transf tp WHERE hd. hst_id = tp. hst_id) bd3, corp_hst tmpcrp, section_hst tmpsec, post_hst tmppst, leave_reason lev WHERE b d0.hst_id = bd1.hst_id AND bd0.hst_id = bd2.hst_id AND bd0.hst_id = bd3.hst_id AND bd0.crp _id = crp.cr p_id(+) AND crp.date_from(+) <= bd0.anc_date AND crp.date_to(+) >= bd0.anc_date AND bd0.org_crp_id = ocrp.crp_id(+) AND ocrp.date_from(+) <= bd0.anc_date AND ocrp.date_to(+) >= bd0.anc_date AND bd0.sec_id = sec.sec_id(+) AND sec.date_from(+) <= bd0.anc_date AND sec.date_to(+) >= bd0.anc_date AND bd0.org_sec_id = osec.sec_id(+) AND osec.date_from(+) <= bd0.anc_date AND osec.date_to(+) >= bd0.anc_date AND bd0.pst_id = pst.pst_id(+) AND pst.date_from(+) <= bd0.anc_date AND pst.date_to(+) >= bd0.anc_date AND bd0.psn_id = psn.psn_id(+) AND psn.date_from(+) <= bd0.anc_date AND psn.date_to(+) >= bd0.anc_date AND bd0.cls_id = cls.cls_id(+) AND cls.date_from(+) <= bd0.anc_date AND cls.date_to(+) >= bd0.anc_date AND bd0.spc_id = spc.spc_id(+) AND spc.date_from(+) <= bd0.anc_date AND spc.date_to(+) >= bd0.anc_date Oracleに完全依存したソフトウェア ● Oracleを完全に使いこなしている訳ではない ● SQLで大体作られている ● とりあえずデータは正規化して突っ込む ● 速度はオプティマイザ頼み ● 3秒くらいで画面が出れば早い方
  8. 8. 8 そして訪れる業務命令 < 遅い
  9. 9. 9 そして訪れる業務命令 < 100msで画面が 出るようにしろ
  10. 10. 10 そして訪れる業務命令 < バッチ処理も 一瞬で終わらせろ
  11. 11. 11 そして訪れる業務命令 < あ、コストはそのままで
  12. 12. 12 100msの速度とは? 画面のレスポンスまでに100msということは 諸々の処理を抜くと、 DBに許された処理時間 = 20ms
  13. 13. 13 20msでのRDB ● 非正規化する ● join禁止 ● ソート済みデータを用意する
  14. 14. 14 試算(実行時ソート) ● 設定 ● CPU 1処理 約0.3[ns] ● CPUキャッシュアクセス速度 0.5~5[ns] ● メモリアクセス速度 10~数10[ns] ● 処理1ループを、100[ns]とする 10万件ソートすると N logN = 1,600,000 ループ
  15. 15. 15 試算(実行時ソート) 1,600,000 * 100[ns] = 160[ms] ● 遅い ● メモリに全部データが載っているとしても なかなか大変な計算 ● コア数にも限界がある
  16. 16. 16 20msでのRDB ● 非正規化する ● join禁止 ● ソート済みデータを用意する → RDBの良さを活かせない領域 → KeyValueStore(KVS)を使ってみる
  17. 17. 17 KeyValueStore(KVS)とは ● PKしかWhere句に書けない ● join不可 ● transactionもあんまりない ● その代わり分散できる
  18. 18. 18 2.KVSで置き換える
  19. 19. 19 下準備 ● 様々な処理を吸収するレイヤとして ObjectMapperを実装 --リストアップ List<Employee> list = kva.search(startWith(“userId”), Employee.class); --insert Employee employee = new Employee(“堤 勇人”, “Tsutsumi Hayato”, ...); kva.insert(employee);
  20. 20. 20 メインDBは? ● 基本的にCassandraに全てのデータを保存する ● RDBは全廃
  21. 21. 21 consistencyは? ● 常に最新のデータが取れるか? ● QUORUMでread/write Write Read
  22. 22. 22 joinは? ● 非正規化データを作成する ● 作っただけでなくメンテナンスする必要がある ● Cassandraへの書き込みをインターセプトして 非正規化データを作成する非同期メッセージを 投げる ● MessageQueueにはkafkaを使用
  23. 23. 23 indexは? ● 別テーブルが作られる。joinと同じ仕組み ● 開発者はannotationを付けるだけ @AutoIndex(Employee.class) @Join(with = Project.class, as = "p", where = {"projectId == p.id"}) class EmployeeWithProjectIndex { @Key private UUID id; private String name; @Column(from = "#p.name") private String projectName; }
  24. 24. 24 sortは? ● そのソート順で並んだ別テーブルを作っておく ● これも同様に処理される class Project{ @Key private UUID id; private String code; private String name; } @AutoIndex(Project.class) class ProjectByUniqueCodeIndex { private UUID id; @Key private String code; private String name; }
  25. 25. 25 group byは? ● Spark, Spark streamingといった分散処理で 予め計算しておく。
  26. 26. 26 部分一致は? ● 全文検索エンジン Elasticsearch を使う ● indexと同様の仕組みでメンテナンスされる @AutoIndex(value = Employee.class, elasticsearchType ="{ElasticsearchTypeName}") @Join(with = Project.class, as = "p", where = "projectId == p.id") class EmployeeWithProjectIndex { @Key private UUID id; private String name; @Column(from = "#p.name") private String projectName; }
  27. 27. 27 sequenceは? ● Counter+Lightweight transactionで実現可能 CQL> UPDATE sequence SET value = 1595 WHERE key = "employee" if value = 1594;
  28. 28. 28 transactionは? ● transactionを使っている箇所を精査していくと 実はほとんどの部分でtransactionは不要。 ● しかし必要な場合もあることは確か。 ● ではどうするか?
  29. 29. 29 transaction - rollbackは? ● rollbackが必要な場合は、結局validationの結果 によってrollbackしたい場合がほとんど ● validationだけならCassandraの機能である、 Lightweight transactionで十分保証できる
  30. 30. 30 transaction - isolationは? ● isolationが必要、つまり同時に入れたデータが 読めるようになるのも同時にしたい場合がある ● 2通りの方法を用意 ● Commit logパターン ● 誤り訂正パターン
  31. 31. 31 transaction - Commit logパターン ● isolationを保つ単位を 一行としてCommit log テーブルに書き込む ● 通常はそのまま読む ● isolationを確保したい場合、 Commit logと対象テーブルを 両方読み、マージする A, B, C A CB Write data Read data Read data with isolation 逐次反映
  32. 32. 32 transaction - 誤り訂正パターン ● 使用したデータのタイムスタンプを記録してお き、処理後一定時間変更が無いかを監視 ● 一定時間は、Messageの処理時間より大きく取 る必要がある
  33. 33. 33 バッチ処理は? ● Spark, Spark streamingといった分散処理技術 ● リソースプランニングやスケジューラはYARN
  34. 34. 34 Datacenter Replicationは? ● Cassandraは、同様の機能を持っているが、 より詳細な設定が必要となる ● あるお客様では東京とシンガポールしかいらな いが、別のお客様では東京とNYが要る、等 ● メッセージを発行して、他のDCに送りつける ● Lightweight Transactionはどこか一つに聞き に行く
  35. 35. 35 データ構造は? ● 業務システムに存在するデータ構造を分類 ● Changeset ● 変更の蓄積。異動情報等の履歴テーブル。 ● Event ● 事実の蓄積。申請書や伝票等。 ● それぞれのパターン毎にAPIを用意
  36. 36. 36 データ構造毎のAPI ● データ構造毎のデータ取得法を抽象化する ● API内部である程度の最適化が可能 --現在日のデータを取得 Employee emp = kva.getChangeset(empId, now(), Employee.class); --過去の申請書をリストアップ Iterator<Expense> ite = kva.search(match(“tsutsumi”, “1094”), Expense.class);
  37. 37. 37 3.リプレースしたメリット・デメリット
  38. 38. 38 やはり難しいところもある…… ● フリーワードで絞り込み検索をした結果を合計する といった予め用意しておけないデータ ● 自由にソートする、自由に検索する ● データの作り方がシステム目線からユーザー目線へ
  39. 39. 39 スケーラビリティがもたらすメリット ● サーバを追加することで高速化 ● 不要な時はサーバを減らすことで コスト削減 ● クラウドと相性が良い
  40. 40. 40 止めない運用 あらゆる操作を動作したまま実行可能 ● スケールアウト、スケールイン ● サーバ置き換え ● テーブル構造変更 ● DBのバージョンアップ
  41. 41. 41 低いレイテンシ ● 応答速度は10ms以下 ● 負荷が上がっても性能を保つ http://googlecloudplatform.blogspot.jp/2014/03/cassandra-hits-one-million-writes-per-second-on-google-compute-engine.html
  42. 42. 42 高いスループット ● 同コストのOracleと比較し、 最大23.5倍の高速化を確認
  43. 43. 43 4.まとめ
  44. 44. 44 まとめ ● Oracleに依存していたパッケージソフトウェア を分散データベースに載せ替えることは可能 ● 相応のメリットがある ● 開発者の頭の切り替えも必要 ● 作成したライブラリは来年以降公開予定
  45. 45. 45 ありがとうございました!

×