Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

5 Webサービスの裏側

Slide 6

Slide 6 text

6 Webサービス(1) ● インターネット上で何かしらの価値を提供するサービス ○ クラウドや*aaSなどと表現することもある ■ SaaS, PaaS, Iaasなど ○ freeeはビジネス向けのサービスを提供 ■ B2B (Business To Business) ○ ブラウザだけでなくiOSやAndroidのアプリからサービスを使 うケースも含める

Slide 7

Slide 7 text

Webサービス(2) 7 ● リクエスト ○ ブラウザやアプリからWebサービスに対して何かの処理を 依頼すること ● レスポンス ○ リクエストに対しての応答 ○ レスポンスの内容に応じてブラウザやアプリが画面を書き換 える

Slide 8

Slide 8 text

8 Webサービスの全般的な要件 ● 使いたいと思っている機能を基本的にはいつでも使える ○ サービスが落ちていると嫌ですよね ● 可能な限り速く結果を返す ○ レスポンスが遅いとイライラしますよね ○ できればミリ秒の単位でレスポンスを返したい ■ 1秒 = 1000ミリ秒 ● ユーザが識別されている ○ プライベートな情報を、自ら公開せずに他人に情報を見られ ると嫌ですよね

Slide 9

Slide 9 text

サービスが常時稼働しているとは? 9 ● 前提:マシンは壊れるもの ○ CPU, メモリ, ストレージ, 電源, などなど ○ ソフトウェアのバグによって機能しなくなることもある ■ OS, ミドルウェア, アプリケーション ● 壊れても大丈夫なように複数のマシンでサービスを動かす ○ 冗長化 ハードウェア(PC, tablet, smartphone等) OS(iOS, MacOS, Windows, Linux等) ミドルウェア アプリケーション

Slide 10

Slide 10 text

レスポンスを速く返すとは? 10 ● 計算を速く終わらせる ○ ハードウェアのスペックをあげる ○ ソフトウェアを効率よく動かす ■ アルゴリズムとデータ構造が特に重要 ○ 不要な計算を後回しにする ● サーバーの忙しさを下げる ○ 少ない計算量でも、同じ処理が1台でたくさん動いていると待た される ■ リクエストを複数の台数に振り分ける ■ 負荷分散と呼ぶ ● 待ち行列を減らす ○ 高速道路の料金所でよく渋滞しますよね(ETCありますが) ○ 待ち行列理論というのがありますが、それは飛ばします

Slide 11

Slide 11 text

冗長化と負荷分散 11 ● 複数台でリクエストを受け付 ける(ロードバランサ) ○ どれか故障してもサービ スを継続できる ● リクエストを処理するのも複 数台用意しておく ○ 一台で処理できる数は限 界がある ○ 複数台あれば限界がN 倍増える ■ ただしお金がかかる

Slide 12

Slide 12 text

データを保存する 12 ● Webサービスは大抵は何かのデータを保存します ○ 会計データ ○ 画像 ○ SNSの投稿 ○ チャットメッセージ ● 保存するためのシステムがあります ○ RDBMS, KVS, … ○ あとで説明予定 これ

Slide 13

Slide 13 text

負荷分散とデータの整合性 13 ● 状態(データ)を持つサーバは処理を分散させるのは難しい ○ 状態を複数のサーバで同じにしないといけない ○ 負荷分散させるためにはある種の諦めが必要 ■ CAP定理 ● Webサーバは状態を持たないのが普通 ○ →増やしやすい 詳細は分散システムの授業で説明があると思います

Slide 14

Slide 14 text

つまりレスポンスを速くするとは 14 ● すべての場所で処理を速く終わらせる ○ ロードバランサ ○ web server ○ 大量データの読み書き トータルで速 くする

Slide 15

Slide 15 text

15 Webサービスとアルゴリズムと データ構造

Slide 16

Slide 16 text

16 すべてを紹介するのは難しいので ● RDBMS (Relational DataBase Management System) ○ データの検索 ○ データの並び替え ○ データの結合 ● KVS (Key Value Store) ● キューシステム

Slide 17

Slide 17 text

17 RDBMS

Slide 18

Slide 18 text

18 RDBMS ● Relational DataBase Management System ○ 簡単に言うと ■ 安全にかつ高速に、大量のデータを保存・検索できるシス テム ○ MySQLやPostgreSQLがよく使われている ○ 大抵のサービスで使われていると思って良い データベースの授業は3年で開講されるそうですが、 その場合は絶対に受けておいたほうが良いです!!

Slide 19

Slide 19 text

RDBMSのイメージ 19 ● スプレッドシートみたいなもの ○ テーブル ○ 行 ○ 列 ● 特徴 ○ 検索ができる ○ 大量データを扱える ○ 同時操作が可能 ○ その他にも色々ありますが、来 年の講義で学んでください

Slide 20

Slide 20 text

SQL 20 ● Structured Query Language ○ RDBMSに命令をするための言語 ○ 宣言的に欲しいデータの検索を記述 ○ データの挿入、更新、削除も可能 ○ どのように検索するかはRDBMSが裏で決める SELECT 学籍番号, 名前 FROM 学生 WHERE 都道府県 = ‘東京都’ 命令:学生というテーブルの中から東京都の学生だけを学 籍番号と名前を抽出したい

Slide 21

Slide 21 text

RDBMSの実装 21 ● 各製品によって挙動は異なります ● あくまでも概念として紹介します ○ 興味ある人はマニュアル or OSSのRDBMSのコードを読んで みてください

Slide 22

Slide 22 text

データの検索 22 ● 線形探索 ○ データをすべて検索する ■ 配列を最初から最後までスキャンするイメージ ○ ストレージの速度が速くなったとは言え、遅い ○ フルスキャンと呼んだりします ● インデックス探索 ○ 次のページから説明します ○ 二分木探索をイメージしてもらえると

Slide 23

Slide 23 text

例:教科書から特定の内容が書いてあるページに飛びたい 23 ● 「クイックソート」というキーワードがあるページを探したい ○ 本が1,000ページあるとする ● 探し方 ○ 巻末にある「索引」から「クイックソート」という単語があるか調べ て、あればそのページに移動する ■ インデックススキャン ○ 本を1ページ目から探していく ■ 1,000ページを読み込まないといけないので時間がかかる ■ 「変数」という一般的な用語だと色々なページに出てくるので 先頭から全部確認したほうが早い ● 意味があるのかは置いておいて

Slide 24

Slide 24 text

B+Tree 24 ● 木構造の一つ ○ インデックス(索引)を表現する一つの方式 ■ 本の最後の方にキーワードが何ページにあるか、というの もインデックスです ○ 2分木も木構造の一つ By Grundprinzip - Own work, CC BY 3.0, https://commons.wikimedia.org/w/index.php?curid=10758840

Slide 25

Slide 25 text

B+Treeの特徴 25 ● 実際のデータは葉にしか持たない ○ B-Treeは節にも持つ ○ ブロックデバイスに適している ■ ブロックデバイスとは簡単に言うと外部ストレージ(HDD, SSD等) ■ 1回のストレージのオペレーションをブロックという塊で操 作する ○ 節を1ブロックに大量に詰め込むことができるので木の高さが 低くなる

Slide 26

Slide 26 text

B+Treeの特徴 26 ● 根から葉への高さは均等 ○ 大量のデータから一つ取り出したいときに、数ブロックスキャ ンすれば到達できる ● 隣のブロックへの参照を持っているので、範囲検索も高速

Slide 27

Slide 27 text

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 -- Insert (an integer) as both key and value). f -- Find the value under key . p -- Print the path from the root to key k and its associated value. r -- Print the keys and values found in the range [, d -- Delete key 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 |

Slide 28

Slide 28 text

ソースコードを追いかけるTips 28 ● デバッガを使うとコードを追いやすいです ○ gdb

Slide 29

Slide 29 text

29 RDBMSでのソート

Slide 30

Slide 30 text

巨大なデータのソート 30 ● ソート例 ○ 学生さんのリストをテストの成績順にソートしたい ● メモリに収まる範囲であればクイックソートでソートする ○ 数百行レベルであれば余裕でメモリ上でソートできる ○ オンメモリで平均的に速いソートアルゴリズム ● メモリに収まりきらない場合はファイルを使ったソート ○ マージソート ○ ファイルを使うので遅い

Slide 31

Slide 31 text

Top-N sort (Top-k selection) 31 ● 並び替えた結果から上位10件を取りたい ○ SELECT * FROM students ORDER BY score DESC LIMIT 10 ○ 該当する行をすべてとってきてソートするのではなく、上位N 件だけを保持してソートする

Slide 32

Slide 32 text

B+Treeの特性を活かしたソート 32 ● B+Treeは順番を保持したデータ構造なので、その特性を活かす ことも可能(検索条件次第)

Slide 33

Slide 33 text

33 テーブル結合

Slide 34

Slide 34 text

テーブル結合とは 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 愛媛県 結合

Slide 35

Slide 35 text

結合例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 愛媛県 結合

Slide 36

Slide 36 text

結合例2 36 ● 特定の学生がどの講義を履修したか? ○ 学籍番号ををキーにテーブルを結合 ○ →学生番号と講義IDを取得可能になる ○ →さらに講義名を取得したい場合は講義テーブルを結合 学籍番号 名前 4 山田 2 田中 1 鈴木 7 木村 学籍番号 講義番号 1 1001 1 2001 4 3001 2 1022 7 4000 2 1001 講義番号 講義名 1001 英語 1022 会計学 3001 ネットワーク 2001 論理学 4000 線形代数 履修テーブル 学生テーブル 講義テーブル

Slide 37

Slide 37 text

テーブル結合(JOIN)をどう実現するか 37 ● 代表的なものは3つのアルゴリズム ○ Nested Loop Join ○ Merge Join ○ Hash Join ● すでに習ったアルゴリズムを組み合わせています ● のちほど3つのアルゴリズムを実装していただきます

Slide 38

Slide 38 text

サンプルデータ 38 4 9 2 1 7 2 10 5 7 2 ● 1次元の整数の配列を2つ用意 ○ 整数は学籍番号や講義番号と思ってください ○ 結合結果の順番は不定 2 2 2 2 7 7 結合

Slide 39

Slide 39 text

Nested Loop Join 39 ● 単純な2重ループのアルゴリズム ○ 全組み合わせを比較し、条件にあったものを返す ○ もう少し丁寧に書くと ■ 駆動表の条件にマッチするのを内部表から持ってくる、と いうのを繰り返す ■ B+Treeでは条件次第では内部表から早くデータを取って これる(下の図はフルスキャン) 4 9 2 1 7 2 10 5 7 2

Slide 40

Slide 40 text

Merge Join 40 ● ソートをあらかじめ両方やってからマージしていく ● 言葉で説明は難しいので擬似コードを書く 4 9 2 1 7 2 10 5 7 2

Slide 41

Slide 41 text

擬似コード (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 } } }

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

44 1 2 4 7 9 2 2 5 7 10 ● 2 == 2 ○ さらに進める ● 結果:{2,2}, {2,2}

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

46 1 2 4 7 9 2 2 5 7 10 ● 4 > 2 ○ 右のテーブルを先に進める ● 結果:{2,2}, {2,2}

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

48 1 2 4 7 9 2 2 5 7 10 ● 4 < 5 ○ 左のテーブルを先に進める ● 結果:{2,2}, {2,2}

Slide 49

Slide 49 text

49 1 2 4 7 9 2 2 5 7 10 ● 7 > 5 ○ 右のテーブルを進める ● 結果:{2,2}, {2,2}

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

52 1 2 4 7 9 2 2 5 7 10 ● 9 > 7 ○ 右のテーブルを進める ● 結果:{2,2}, {2,2}, {7,7}

Slide 53

Slide 53 text

53 1 2 4 7 9 2 2 5 7 10 ● 9 < 10 ○ 右のテーブルを進めたいがこれ以上無いので終了 ● 結果:{2,2}, {2,2}, {7,7}

Slide 54

Slide 54 text

擬似コード(再掲) 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 } } }

Slide 55

Slide 55 text

Hash Join 55 ● 条件となる値をキーにしてハッシュテーブルを作る ○ どちらか小さいテーブル ○ ハッシュテーブルの特性上、JOINの条件が範囲条件の場合 は使えない 4 9 2 1 7 2 10 5 7 2 ハッシュテーブル

Slide 56

Slide 56 text

練習問題 56 ● 以下のJOINアルゴリズムをC言語で実装してください ○ Nested Loop Join ○ Merge Join ■ ソートは何で実装しても良いです ○ Hash Join ■ ハッシュテーブルは何で実装しても良いです ● それぞれのJoinについてどういう特性があるか考えてみてくださ い

Slide 57

Slide 57 text

練習問題 57 ● 入力 ○ 配列の長さNとそれに続くデータを駆動表・内部表で用意 ■ 3種類を用意 ○ ランダムに10万件の数字を生成するスクリプトも作ってみてくだ さい ■ 余裕があれば 3 // 駆動表のサイズ 2 1 3 4 // 内部表のサイズ 3 2 3 1

Slide 58

Slide 58 text

練習問題 58 ● 出力 ○ マッチした値と件数 ■ 重複分も含める ■ マッチした値の順番は問いません ■ 件数がそれぞれのJOINで同じことを確認する 1 1 2 2 3 3 3 3 join count = 4

Slide 59

Slide 59 text

59 KVS(Key Value Store)

Slide 60

Slide 60 text

KVS 60 ● KVSはいろいろなミドルウェアがある ○ Keyとそれに対するValueを保持する ■ Keyでデータを検索 ○ 代表的なものは連想配列をハッシュテーブルを使って実装 ● key-valueをオンメモリで持っておく実装が多いシステム ○ データを永続化できるものもある ○ キャッシュ用途に使われることが多い ○ memoryが溢れそうな場合はLRU(Least Recently Used)等の ポリシーで消すこともある

Slide 61

Slide 61 text

KVSが向かないケース 61 ● 集計や結合などのデータに対して複雑な操作が必要な場合は RDBMS ● キーの範囲検索 ○ 製品(LevelDB等)によってはできるので全てではない

Slide 62

Slide 62 text

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は実際 はもっと長い)

Slide 63

Slide 63 text

63 キューの応用例

Slide 64

Slide 64 text

キューの前に 64 ● Webサーバは基本的に早く応答を返したい ○ 重い処理を後回しにしたい ● リクエストの同期処理と非同期処理 ○ 同期処理とはユーザへ応答を返すときには処理が終わって いる処理 ○ 非同期処理とはユーザへ応答を返すのとは別に裏で行われ る処理 ■ 別の形でユーザへ通知するか、そもそも通知が不要なも のもある

Slide 65

Slide 65 text

処理を後回しにしたい例 65 ● 使い方例 ○ Webサーバがリクエストを受け付けて、裏で重い処理をする ○ ログをキューに投げて、裏でデータ分析用の基盤に投げる ○ メール送信等の多少遅れても問題ない処理をする

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

68 まとめ

Slide 69

Slide 69 text

アルゴリズムとデータ構造を知っておくと良いこと 69 ● データ構造とアルゴリズムは色々なところで使われている ○ それぞれ特性があるので、状況に応じて使い分けることが大 事 ■ 外部記憶領域に書き出す可能性があるからクイックソート ではなくマージソートを使う ■ Merge Joinは結合の条件比較の数は少ないが、その代 わりに先にソートする必要がある、等 ○ レスポンスが遅くなったときには裏でどういうアルゴリズムが 動いているかを知っているかで解決ができる つまり、サービス開発には欠かせない知識!

Slide 70

Slide 70 text

スモールビジネスに携わるすべての人が 創造的な活動にフォーカスできるよう