Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

2015年5o月にfreee株式会社へ入社 執行役員 プロダクト基盤(SREなど)本部長 RDBMSと運用自動化が大好き 学生時代 形式仕様言語の研究とACM/ICPC 社会人 SRA→Microsoft→グリー→スタートアップ2社→freee Yoshiyuki Asaba 浅羽 義之 freee株式会社 2

Slide 3

Slide 3 text

3     アイデアやパッションやスキルがあればだれでも、 ビジネスを強くスマートに育てられるプラットフォームをつくる スモールビジネスを、世界の主役に。

Slide 4

Slide 4 text

4 創業からIPOまで、中小企業活性化のためのサービスを一気通貫で提供 freee会社概要 ❂ 納税する ↗ 育てる ↻ 運営する ✩ はじめる 会社設立 freee 開業 freee クラウド会計ソフト freee 人事労務 freee (マイナンバー管理 freee 含む) クラウド申告 freee 161億603万円 (資本準備金等含む) 従業員数 事業内容 クラウド型バックオフィスサービスの開発・販売 資本金 設立年月日 2012年7月 465名(2018年6月末時点) 2017年「働きがいのある会社」 ランキング3位

Slide 5

Slide 5 text

5 100万 サービス開始5年で 1,000,000 事業所数累計 事業所突破 No.1 シェア* ※出典:BCN クラウド会計ソフト市場調査。n=418、webアンケート調査

Slide 6

Slide 6 text

01 Webサービスの裏側 なぜアルゴリズムとデータ構造が必要なのか 6 Section

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

9 Webサービスの一般的な要件 基本的にはいつでも使える ● サービスが落ちていると嫌ですよね 可能な限り速く結果を返す ● レスポンスが速いほうがサクサクサービスを使えて良いですよね ● できればミリ秒単位で結果を返したい ○ 1秒 = 1,000ミリ秒 ユーザーを識別する ● ログインすることによって、自分専用のサービス提供をしてほしいですよね

Slide 10

Slide 10 text

10 サービスが常時稼働しているとは? 前提:マシンは壊れるもの ● CPU, メモリ, ストレージ, その他パーツなど ● ソフトウェアのバグによって機能しなくなることもある ○ 物理的に壊れなくても、OS, ミドルウェア, アプリケーションが壊れることによって事実上 の壊れた状態になることも 壊れても大丈夫なように複数のマシンでサービスを動かす ● 「冗長化」と呼んだりします ハードウェア(PC, tablet, smartphone等) OS(iOS, MacOS, Windows, Linux等) ミドルウェア アプリケーション

Slide 11

Slide 11 text

11 レスポンスを速く返すとは? 計算を速く終わらせる ● ハードウェアのスペックをあげる ● ソフトウェアを効率よく動かす ○ アルゴリズムとデータ構造が特に重要 ● 不要な計算を後回しにする サーバーの忙しさを下げる ● 少ない計算量でも、同じ処理が一台でたくさん動いている と待たされる ○ リクエストを複数のサーバーに振り分ける ○ 負荷分散と呼ぶ 待ち行列 ● リクエストを即座に処理し始める(待たせない)

Slide 12

Slide 12 text

12 冗長化と負荷分散 複数台でリクエストを受け付ける ● どれかが故障してもサービスを継続できる ● 受け付けるだけで、処理は別で行う(転送する) リクエストを処理するサーバーも複数用意 ● Webサーバー、アプリケーションサーバーと呼ぶ ● 一台で処理できる数は限界がある ● 複数台あれば限界が理論上はN倍増える ○ ただしお金がかかる

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

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

02 RDBMS概要 17 Section

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

03 RDBMS上での検索 22 Section

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

25 B+Tree 木構造の一つ ● インデックス(索引)を表現するデータ構造の一つ ● ソート済みのデータを保持する ● メモリ上で収まりきらないようなデータを効率よく扱えるように工夫されている ○ 前提:ストレージのオペレーションは遅い インデックス探索 ● 次のページから説明します ● 二分木探索をイメージしてもらえると By Grundprinzip - Own work, CC BY 3.0, https://commons.wikimedia.org/w/index.php?curid=10758840

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

28 B+Treeの挙動を知りたい場合 小さい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 29

Slide 29 text

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

Slide 30

Slide 30 text

04 RDBMSのソート 30 Section

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

05 RDBMSのテーブル結合 34 Section

Slide 35

Slide 35 text

35 テーブル結合とは 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 36

Slide 36 text

36 結合例1 特定の学生がどこ出身か? ● 都道府県コードをキーにテーブルを結合 ● →学籍番号と都道府県名を取得可能になる 学籍番号 都道府県 コード 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 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

39 サンプルデータ 1次元の整数の配列を2つ用意 ● 整数は学籍番号や講義番号だと思ってください ● 結合結果の順番は不定 4 山田 9 高橋 2 田中 1 鈴木 7 木村 2 1022 10 2001 5 1001 7 1003 2 5000 2 田中 2 1022 2 田中 2 5000 7 木村 7 1003 結合 学生テーブル 履修テーブル

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

42 擬似コード (PostgreSQLソースコードのコメントより引用) 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 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

60 サンプル解答 https://github.com/y-asaba/RDBMS-join-exercise

Slide 61

Slide 61 text

06 KVS(Key Value Store) 61 Section

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

64 KVSの使用例 sessionデータを一時的に保存し、リクエストごとに参照 ● sessionとはサービスにログインされると作られるデータ ● ハッシュテーブルはO(1) ● B+TreeはO(log_b N) ○ bはどれくらい説に詰め込めるか(2分木の場合は2) ○ 外部ストレージへのI/Oも発生する可能性がある web server web server session key value Athoh4Phu0aeng9wureJ Aさんの識別子 fohphaChahmoo1saizuu Bさんの識別子 Aeng6ei1phei0LohQu8i Cさんの識別子 GET (sessionの有効性の確認) SET (login時) ハッシュテーブル (session keyは実際はもっと長い)

Slide 65

Slide 65 text

07 キューの応用例 65 Section

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

69 mkfifoコマンドを使った簡単な実験 コンソールを2つ立ち上げてください(Windowsだと動かないかも) ● mkfifoを通してメッセージを送って処理をします ● 整数を送って、2倍した値を出力する % mkfifo waseda % tail -f waseda | awk '{print $1*2}' 200 2 4 6 8 10 % echo 200 > waseda % seq 5 > waseda キューを待ち受ける キューにデータを入れる

Slide 70

Slide 70 text

08 まとめ 70 Section

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

スモールビジネスを、 世界の主役に。