早稲田大学アルゴリズムとデータ構造特別講義

 早稲田大学アルゴリズムとデータ構造特別講義

82f797c1864841a4aca94079b8508004?s=128

Yoshiyuki Asaba

December 23, 2017
Tweet

Transcript

  1. Webサービスとアルゴリズムとデータ構造 freee株式会社

  2. 自己紹介 2 浅羽義之 Yoshiyuki Asaba プロダクト基盤(SREなど)本部長 • RDBMSと自動化が大好き 学生時代:形式仕様言語研究とACM-ICPC

  3. 目次 3 • freee株式会社の紹介 • webサービスの仕組み ◦ なぜアルゴリズムやデータ構造が必要か? • webサービスで使われているアルゴリズムをいくつか紹介

  4. ビジネスのはじまりから成長をすべてサポートする freee 4 簡単:知識がなくても1クリックで給 与計算 勤怠:勤怠管理も簡単に オンライン:給与明細はオンラインで 配布 会計連動:会計ソフトと完全データ 連携

    政府連携:行政手続きもオンライン で完結 マイナンバー:マイナンバー管理も 完全対応 5分:会社設立用の書類を最短5 分で作成 モバイル:スマホ完全対応で、どこ でも会社設立 ワンストップ:実印発注や銀行口 座作成もできる 自動:銀行やカードの口座と連携し、人工 知能で会計帳簿を作成 簡単:簿記の用語を使わない画面設計で 簡単に使える 最適化:請求書発行や経費精算などの業 務も最適化 実績:クラウド会計ソフトシェア No.1 で安 心の実績 サポート:チャットによる迅速なサポートを 提供 決算:決算や個人事業主の申告まで自動 で簡単に ✩ はじめる ↻ 運営する ↗ 育てる 会社設立 freee (2015年6月リリース) クラウド会計ソフト freee (2013年3月リリース) 人事労務 freee (2014年5月リリース) シェアNo.1 シェアNo.1 開業 freee (2016年10月リリース)
  5. 5 Webサービスの裏側

  6. 6 Webサービス(1) • インターネット上で何かしらの価値を提供するサービス ◦ クラウドや*aaSなどと表現することもある ▪ SaaS, PaaS, Iaasなど

    ◦ freeeはビジネス向けのサービスを提供 ▪ B2B (Business To Business) ◦ ブラウザだけでなくiOSやAndroidのアプリからサービスを使 うケースも含める
  7. Webサービス(2) 7 • リクエスト ◦ ブラウザやアプリからWebサービスに対して何かの処理を 依頼すること • レスポンス ◦

    リクエストに対しての応答 ◦ レスポンスの内容に応じてブラウザやアプリが画面を書き換 える
  8. 8 Webサービスの全般的な要件 • 使いたいと思っている機能を基本的にはいつでも使える ◦ サービスが落ちていると嫌ですよね • 可能な限り速く結果を返す ◦ レスポンスが遅いとイライラしますよね

    ◦ できればミリ秒の単位でレスポンスを返したい ▪ 1秒 = 1000ミリ秒 • ユーザが識別されている ◦ プライベートな情報を、自ら公開せずに他人に情報を見られ ると嫌ですよね
  9. サービスが常時稼働しているとは? 9 • 前提:マシンは壊れるもの ◦ CPU, メモリ, ストレージ, 電源, などなど

    ◦ ソフトウェアのバグによって機能しなくなることもある ▪ OS, ミドルウェア, アプリケーション • 壊れても大丈夫なように複数のマシンでサービスを動かす ◦ 冗長化 ハードウェア(PC, tablet, smartphone等) OS(iOS, MacOS, Windows, Linux等) ミドルウェア アプリケーション
  10. レスポンスを速く返すとは? 10 • 計算を速く終わらせる ◦ ハードウェアのスペックをあげる ◦ ソフトウェアを効率よく動かす ▪ アルゴリズムとデータ構造が特に重要

    ◦ 不要な計算を後回しにする • サーバーの忙しさを下げる ◦ 少ない計算量でも、同じ処理が1台でたくさん動いていると待た される ▪ リクエストを複数の台数に振り分ける ▪ 負荷分散と呼ぶ • 待ち行列を減らす ◦ 高速道路の料金所でよく渋滞しますよね(ETCありますが) ◦ 待ち行列理論というのがありますが、それは飛ばします
  11. 冗長化と負荷分散 11 • 複数台でリクエストを受け付 ける(ロードバランサ) ◦ どれか故障してもサービ スを継続できる • リクエストを処理するのも複

    数台用意しておく ◦ 一台で処理できる数は限 界がある ◦ 複数台あれば限界がN 倍増える ▪ ただしお金がかかる
  12. データを保存する 12 • Webサービスは大抵は何かのデータを保存します ◦ 会計データ ◦ 画像 ◦ SNSの投稿

    ◦ チャットメッセージ • 保存するためのシステムがあります ◦ RDBMS, KVS, … ◦ あとで説明予定 これ
  13. 負荷分散とデータの整合性 13 • 状態(データ)を持つサーバは処理を分散させるのは難しい ◦ 状態を複数のサーバで同じにしないといけない ◦ 負荷分散させるためにはある種の諦めが必要 ▪ CAP定理

    • Webサーバは状態を持たないのが普通 ◦ →増やしやすい 詳細は分散システムの授業で説明があると思います
  14. つまりレスポンスを速くするとは 14 • すべての場所で処理を速く終わらせる ◦ ロードバランサ ◦ web server ◦

    大量データの読み書き トータルで速 くする
  15. 15 Webサービスとアルゴリズムと データ構造

  16. 16 すべてを紹介するのは難しいので • RDBMS (Relational DataBase Management System) ◦ データの検索

    ◦ データの並び替え ◦ データの結合 • KVS (Key Value Store) • キューシステム
  17. 17 RDBMS

  18. 18 RDBMS • Relational DataBase Management System ◦ 簡単に言うと ▪

    安全にかつ高速に、大量のデータを保存・検索できるシス テム ◦ MySQLやPostgreSQLがよく使われている ◦ 大抵のサービスで使われていると思って良い データベースの授業は3年で開講されるそうですが、 その場合は絶対に受けておいたほうが良いです!!
  19. RDBMSのイメージ 19 • スプレッドシートみたいなもの ◦ テーブル ◦ 行 ◦ 列

    • 特徴 ◦ 検索ができる ◦ 大量データを扱える ◦ 同時操作が可能 ◦ その他にも色々ありますが、来 年の講義で学んでください
  20. SQL 20 • Structured Query Language ◦ RDBMSに命令をするための言語 ◦ 宣言的に欲しいデータの検索を記述

    ◦ データの挿入、更新、削除も可能 ◦ どのように検索するかはRDBMSが裏で決める SELECT 学籍番号, 名前 FROM 学生 WHERE 都道府県 = ‘東京都’ 命令:学生というテーブルの中から東京都の学生だけを学 籍番号と名前を抽出したい
  21. RDBMSの実装 21 • 各製品によって挙動は異なります • あくまでも概念として紹介します ◦ 興味ある人はマニュアル or OSSのRDBMSのコードを読んで

    みてください
  22. データの検索 22 • 線形探索 ◦ データをすべて検索する ▪ 配列を最初から最後までスキャンするイメージ ◦ ストレージの速度が速くなったとは言え、遅い

    ◦ フルスキャンと呼んだりします • インデックス探索 ◦ 次のページから説明します ◦ 二分木探索をイメージしてもらえると
  23. 例:教科書から特定の内容が書いてあるページに飛びたい 23 • 「クイックソート」というキーワードがあるページを探したい ◦ 本が1,000ページあるとする • 探し方 ◦ 巻末にある「索引」から「クイックソート」という単語があるか調べ

    て、あればそのページに移動する ▪ インデックススキャン ◦ 本を1ページ目から探していく ▪ 1,000ページを読み込まないといけないので時間がかかる ▪ 「変数」という一般的な用語だと色々なページに出てくるので 先頭から全部確認したほうが早い • 意味があるのかは置いておいて
  24. B+Tree 24 • 木構造の一つ ◦ インデックス(索引)を表現する一つの方式 ▪ 本の最後の方にキーワードが何ページにあるか、というの もインデックスです ◦

    2分木も木構造の一つ By Grundprinzip - Own work, CC BY 3.0, https://commons.wikimedia.org/w/index.php?curid=10758840
  25. B+Treeの特徴 25 • 実際のデータは葉にしか持たない ◦ B-Treeは節にも持つ ◦ ブロックデバイスに適している ▪ ブロックデバイスとは簡単に言うと外部ストレージ(HDD,

    SSD等) ▪ 1回のストレージのオペレーションをブロックという塊で操 作する ◦ 節を1ブロックに大量に詰め込むことができるので木の高さが 低くなる
  26. B+Treeの特徴 26 • 根から葉への高さは均等 ◦ 大量のデータから一つ取り出したいときに、数ブロックスキャ ンすれば到達できる • 隣のブロックへの参照を持っているので、範囲検索も高速

  27. B+Treeの挙動を知りたい場合 27 • 小さいCのコードがあります ◦ http://www.amittai.com/prose/bplustree.html $ gcc -g -O0

    btp.c $ ./a.out ... Enter any of the following commands after the prompt > : i <k> -- Insert <k> (an integer) as both key and value). f <k> -- Find the value under key <k>. p <k> -- Print the path from the root to key k and its associated value. r <k1> <k2> -- Print the keys and values found in the range [<k1>, <k2> d <k> -- Delete key <k> and its associated value. x -- Destroy the whole tree. Start again with an empty tree of the same order. t -- Print the B+ tree. l -- Print the keys of the leaves (bottom row of the tree). v -- Toggle output of pointer addresses ("verbose") in tree and leaves. q -- Quit. (Or use Ctl-D.) ? -- Print this help message. > i 3 3 |
  28. ソースコードを追いかけるTips 28 • デバッガを使うとコードを追いやすいです ◦ gdb

  29. 29 RDBMSでのソート

  30. 巨大なデータのソート 30 • ソート例 ◦ 学生さんのリストをテストの成績順にソートしたい • メモリに収まる範囲であればクイックソートでソートする ◦ 数百行レベルであれば余裕でメモリ上でソートできる

    ◦ オンメモリで平均的に速いソートアルゴリズム • メモリに収まりきらない場合はファイルを使ったソート ◦ マージソート ◦ ファイルを使うので遅い
  31. Top-N sort (Top-k selection) 31 • 並び替えた結果から上位10件を取りたい ◦ SELECT *

    FROM students ORDER BY score DESC LIMIT 10 ◦ 該当する行をすべてとってきてソートするのではなく、上位N 件だけを保持してソートする
  32. B+Treeの特性を活かしたソート 32 • B+Treeは順番を保持したデータ構造なので、その特性を活かす ことも可能(検索条件次第)

  33. 33 テーブル結合

  34. テーブル結合とは 34 • 2つのテーブルを指定した条件で別のテーブルを作る(結合, JOIN)すること ◦ 例:数字が一致する行を結合したい 学籍番号 都道府県 コード

    4 101 2 102 1 102 7 104 都道府県 コード 都道府県名 101 東京都 102 神奈川県 103 長野県 104 愛媛県 駆動表 内部表 4 101 101 東京都 2 102 102 神奈川県 1 102 102 神奈川県 7 104 104 愛媛県 結合
  35. 結合例1 35 • 特定の学生がどこ出身か? ◦ 都道府県コードをキーにテーブルを結合 ◦ →学籍番号と都道府県名を取得可能になる 学籍番号 都道府県

    コード 4 101 2 102 1 102 7 104 都道府県 コード 都道府県名 101 東京都 102 神奈川県 103 長野県 104 愛媛県 学生テーブル 都道府県テーブル 4 101 101 東京都 2 102 102 神奈川県 1 102 102 神奈川県 7 104 104 愛媛県 結合
  36. 結合例2 36 • 特定の学生がどの講義を履修したか? ◦ 学籍番号ををキーにテーブルを結合 ◦ →学生番号と講義IDを取得可能になる ◦ →さらに講義名を取得したい場合は講義テーブルを結合

    学籍番号 名前 4 山田 2 田中 1 鈴木 7 木村 学籍番号 講義番号 1 1001 1 2001 4 3001 2 1022 7 4000 2 1001 講義番号 講義名 1001 英語 1022 会計学 3001 ネットワーク 2001 論理学 4000 線形代数 履修テーブル 学生テーブル 講義テーブル
  37. テーブル結合(JOIN)をどう実現するか 37 • 代表的なものは3つのアルゴリズム ◦ Nested Loop Join ◦ Merge

    Join ◦ Hash Join • すでに習ったアルゴリズムを組み合わせています • のちほど3つのアルゴリズムを実装していただきます
  38. サンプルデータ 38 4 9 2 1 7 2 10 5

    7 2 • 1次元の整数の配列を2つ用意 ◦ 整数は学籍番号や講義番号と思ってください ◦ 結合結果の順番は不定 2 2 2 2 7 7 結合
  39. Nested Loop Join 39 • 単純な2重ループのアルゴリズム ◦ 全組み合わせを比較し、条件にあったものを返す ◦ もう少し丁寧に書くと

    ▪ 駆動表の条件にマッチするのを内部表から持ってくる、と いうのを繰り返す ▪ B+Treeでは条件次第では内部表から早くデータを取って これる(下の図はフルスキャン) 4 9 2 1 7 2 10 5 7 2
  40. Merge Join 40 • ソートをあらかじめ両方やってからマージしていく • 言葉で説明は難しいので擬似コードを書く 4 9 2

    1 7 2 10 5 7 2
  41. 擬似コード (PostgreSQLソースコードのコメントより引用) 41 Join { get initial outer and inner

    tuples INITIALIZE do forever { while (outer != inner) { SKIP_TEST if (outer < inner) advance outer SKIPOUTER_ADVANCE else advance inner SKIPINNER_ADVANCE } mark inner position SKIP_TEST do forever { while (outer == inner) { join tuples JOINTUPLES advance inner position NEXTINNER } advance outer position NEXTOUTER if (outer == mark) TESTOUTER restore inner position to mark TESTOUTER else break // return to top of outer loop } } }
  42. 42 1 2 4 7 9 2 2 5 7

    10 • 両方のデータをソートしてからスタート ◦ 現在の場所を両方のテーブルにマークする ◦ 1 != 2なので左をずらす
  43. 43 1 2 4 7 9 2 2 5 7

    10 • 2 == 2 ◦ どこから一致したかをマークする • 結果:{2,2}
  44. 44 1 2 4 7 9 2 2 5 7

    10 • 2 == 2 ◦ さらに進める • 結果:{2,2}, {2,2}
  45. 45 1 2 4 7 9 2 2 5 7

    10 • 2 < 5 ◦ 左のテーブルを先に進める ◦ 右のテーブルのマークを戻す • 結果:{2,2}, {2,2}
  46. 46 1 2 4 7 9 2 2 5 7

    10 • 4 > 2 ◦ 右のテーブルを先に進める • 結果:{2,2}, {2,2}
  47. 47 1 2 4 7 9 2 2 5 7

    10 • 4 > 2 ◦ 右のテーブルを先に進める • 結果:{2,2}, {2,2}
  48. 48 1 2 4 7 9 2 2 5 7

    10 • 4 < 5 ◦ 左のテーブルを先に進める • 結果:{2,2}, {2,2}
  49. 49 1 2 4 7 9 2 2 5 7

    10 • 7 > 5 ◦ 右のテーブルを進める • 結果:{2,2}, {2,2}
  50. 50 1 2 4 7 9 2 2 5 7

    10 • 7 == 7 ◦ どこから一致したかをマークする ◦ 右のテーブルを進める • 結果:{2,2}, {2,2}, {7,7}
  51. 51 1 2 4 7 9 2 2 5 7

    10 • 7 < 10 ◦ 右のテーブルのマークを戻す ◦ 左のテーブルを進める • 結果:{2,2}, {2,2}, {7,7}
  52. 52 1 2 4 7 9 2 2 5 7

    10 • 9 > 7 ◦ 右のテーブルを進める • 結果:{2,2}, {2,2}, {7,7}
  53. 53 1 2 4 7 9 2 2 5 7

    10 • 9 < 10 ◦ 右のテーブルを進めたいがこれ以上無いので終了 • 結果:{2,2}, {2,2}, {7,7}
  54. 擬似コード(再掲) 54 Join { get initial outer and inner tuples

    INITIALIZE do forever { while (outer != inner) { SKIP_TEST if (outer < inner) advance outer SKIPOUTER_ADVANCE else advance inner SKIPINNER_ADVANCE } mark inner position SKIP_TEST do forever { while (outer == inner) { join tuples JOINTUPLES advance inner position NEXTINNER } advance outer position NEXTOUTER if (outer == mark) TESTOUTER restore inner position to mark TESTOUTER else break // return to top of outer loop } } }
  55. Hash Join 55 • 条件となる値をキーにしてハッシュテーブルを作る ◦ どちらか小さいテーブル ◦ ハッシュテーブルの特性上、JOINの条件が範囲条件の場合 は使えない

    4 9 2 1 7 2 10 5 7 2 ハッシュテーブル
  56. 練習問題 56 • 以下のJOINアルゴリズムをC言語で実装してください ◦ Nested Loop Join ◦ Merge

    Join ▪ ソートは何で実装しても良いです ◦ Hash Join ▪ ハッシュテーブルは何で実装しても良いです • それぞれのJoinについてどういう特性があるか考えてみてくださ い
  57. 練習問題 57 • 入力 ◦ 配列の長さNとそれに続くデータを駆動表・内部表で用意 ▪ 3種類を用意 ◦ ランダムに10万件の数字を生成するスクリプトも作ってみてくだ

    さい ▪ 余裕があれば 3 // 駆動表のサイズ 2 1 3 4 // 内部表のサイズ 3 2 3 1
  58. 練習問題 58 • 出力 ◦ マッチした値と件数 ▪ 重複分も含める ▪ マッチした値の順番は問いません

    ▪ 件数がそれぞれのJOINで同じことを確認する 1 1 2 2 3 3 3 3 join count = 4
  59. 59 KVS(Key Value Store)

  60. KVS 60 • KVSはいろいろなミドルウェアがある ◦ Keyとそれに対するValueを保持する ▪ Keyでデータを検索 ◦ 代表的なものは連想配列をハッシュテーブルを使って実装

    • key-valueをオンメモリで持っておく実装が多いシステム ◦ データを永続化できるものもある ◦ キャッシュ用途に使われることが多い ◦ memoryが溢れそうな場合はLRU(Least Recently Used)等の ポリシーで消すこともある
  61. KVSが向かないケース 61 • 集計や結合などのデータに対して複雑な操作が必要な場合は RDBMS • キーの範囲検索 ◦ 製品(LevelDB等)によってはできるので全てではない

  62. KVSの使用例 62 • sessionデータを一時的に保存し、リクエストごとに参照 ◦ sessionとはサービスにログインされると作られるデータ ◦ ハッシュテーブルはO(1) ◦ B+TreeはO(log_b

    N) ▪ bはどれくらい節に詰め込めるか(2分木だと2) ▪ 外部ストレージへのI/Oも発生する可能性がある web server web server SET (login時) GET (sessionの有効性の確認) session key value Athoh4Phu0aeng9wureJ Aさんの識別子 fohphaChahmoo1saizuu Bさんの識別子 Aeng6ei1phei0LohQu8i Cさんの識別子 ハッシュテーブル (session keyは実際 はもっと長い)
  63. 63 キューの応用例

  64. キューの前に 64 • Webサーバは基本的に早く応答を返したい ◦ 重い処理を後回しにしたい • リクエストの同期処理と非同期処理 ◦ 同期処理とはユーザへ応答を返すときには処理が終わって

    いる処理 ◦ 非同期処理とはユーザへ応答を返すのとは別に裏で行われ る処理 ▪ 別の形でユーザへ通知するか、そもそも通知が不要なも のもある
  65. 処理を後回しにしたい例 65 • 使い方例 ◦ Webサーバがリクエストを受け付けて、裏で重い処理をする ◦ ログをキューに投げて、裏でデータ分析用の基盤に投げる ◦ メール送信等の多少遅れても問題ない処理をする

  66. キューの応用例 66 • キューを管理するミドルウェアもしくはサービスがある ◦ リクエストを受けたサーバがメッセージをキューに入れる ◦ 誰かがキューからメッセージを拾ったら、他の人は拾わない(アト ミックな処理) Web

    Server Web Server Job Worker Job Worker push pull Queue Service
  67. mkfifoコマンドを使った簡単な実験 67 • コンソールを2つ立ち上げてください(windowsだと動かないかも) ◦ mkfifoを通してメッセージを送る % mkfifo waseda %

    tail -f waseda waseda university 1 2 3 4 5 % echo waseda university > waseda % for i in `seq 5`; do echo $i > waseda; done
  68. 68 まとめ

  69. アルゴリズムとデータ構造を知っておくと良いこと 69 • データ構造とアルゴリズムは色々なところで使われている ◦ それぞれ特性があるので、状況に応じて使い分けることが大 事 ▪ 外部記憶領域に書き出す可能性があるからクイックソート ではなくマージソートを使う

    ▪ Merge Joinは結合の条件比較の数は少ないが、その代 わりに先にソートする必要がある、等 ◦ レスポンスが遅くなったときには裏でどういうアルゴリズムが 動いているかを知っているかで解決ができる つまり、サービス開発には欠かせない知識!
  70. スモールビジネスに携わるすべての人が 創造的な活動にフォーカスできるよう