Data Engineering at VOYAGE GROUP #jawsdays

7,512 views

Published on

#jawsdays 2015での発表スライドです。
http://jawsdays2015.jaws-ug.jp/speaker/suzuki/

Published in: Technology

Data Engineering at VOYAGE GROUP #jawsdays

  1. 1. Data Engineering at VOYAGE GROUP JAWS DAYS 2015 2015/03/22 @suzu_v
  2. 2. 自己紹介 • 鈴木健太、すずけん、@suzu_v • http://suzuken.hatenablog.jp/ • ソフトウェアエンジニア • アドテクノロジー事業(SSP, DMP)に従事
  3. 3. https://www.facebook.com/voyagegroup/photos/a.365470036810049.90562.176439939046394/752116391478743/?type=3&permPage=1
  4. 4. データエンジニアリング • 日々増え続けるデータをビジネスに活かし、ユーザ に恩恵を届けるためには、信頼性の高いデータの保 持、処理、そしてクエリ可能な状態をつくる必要が ある。そのために、スケーラブルで信頼性の高いデー タ基盤をつくり、データのパイプラインを組み立て るエンジニアリングのこと
  5. 5. 私達とAWS • 2009年から利用開始 • 2011年からアドテクノロジー領域でも利用を開始 • 今日はアドテクノロジー領域でのAWS利用につい てお話します
  6. 6. ディスプレイ広告
  7. 7. 広告リクエスト ブラウザ アドサーバ
  8. 8. そのときどきで良さそうな 広告を選んで ブラウザ アドサーバ 広告 広告 広告
  9. 9. 広告を表示する ブラウザ アドサーバ 広告 広告 広告
  10. 10. ex. 行動ターゲティング基盤 アーキテクチャ
  11. 11. 行動ターゲティングの課題 • なるべく速く書き込みたい。ユーザが何かをみたら、 すぐにターゲティング可能な状態にしてほしい。反 映が速ければ速いほどいい。 • 案件や対象ユーザが増えても、システム全体が問題 なくスケールすること • 読み込みが安定して低レイテンシであること。でき れば5ms以内。
  12. 12. Targeting Infrastructure ELB EC2 EC2 EC2 EC2 request EC2 S3 DynamoDB EMR ELB EC2 EC2 EC2 EC2 http api fluentd fluentd (aggregator) out_exec_filter out_dynamodb servlet (scala) dynamic-dynamo EC2 Growth Forecast EC2 EC2 VPC 1 VPC 1 VPC 2 (targeting) VPC Peering VPC Peering ephemeral cluster
  13. 13. ELB EC2 EC2 EC2 EC2 request EC2 S3 DynamoDB EMR ELB EC2 EC2 EC2 EC2 http api fluentd fluentd (aggregator) out_exec_filter out_dynamodb servlet (scala) dynamic-dynamo EC2 Growth Forecast EC2 EC2 VPC 1 VPC 1 VPC 2 (targeting) VPC Peering VPC Peering ephemeral cluster 配信用VPC ターゲティング 基盤VPC
  14. 14. ELB EC2 EC2 EC2 EC2 request EC2 S3 DynamoDB EMR ELB EC2 EC2 EC2 EC2 http api fluentd fluentd (aggregator) out_exec_filter out_dynamodb servlet (scala) dynamic-dynamo EC2 Growth Forecast EC2 EC2 VPC 1 VPC 1 VPC 2 (targeting) VPC Peering VPC Peering ephemeral cluster Fluentdの forwardで連携
  15. 15. ELB EC2 EC2 EC2 EC2 request EC2 S3 DynamoDB EMR ELB EC2 EC2 EC2 EC2 http api fluentd fluentd (aggregator) out_exec_filter out_dynamodb servlet (scala) dynamic-dynamo EC2 Growth Forecast EC2 EC2 VPC 1 VPC 1 VPC 2 (targeting) VPC Peering VPC Peering ephemeral cluster Event Streamノード c3.xlarge複数台 td-agent2
  16. 16. ELB EC2 EC2 EC2 EC2 request EC2 S3 DynamoDB EMR ELB EC2 EC2 EC2 EC2 http api fluentd fluentd (aggregator) out_exec_filter out_dynamodb servlet (scala) dynamic-dynamo EC2 Growth Forecast EC2 EC2 VPC 1 VPC 1 VPC 2 (targeting) VPC Peering VPC Peering ephemeral cluster out_exec_filterでログを加工 DynamoDBに書き込み
  17. 17. ELB EC2 EC2 EC2 EC2 request EC2 S3 DynamoDB EMR ELB EC2 EC2 EC2 EC2 http api fluentd fluentd (aggregator) out_exec_filter out_dynamodb servlet (scala) dynamic-dynamo EC2 Growth Forecast EC2 EC2 VPC 1 VPC 1 VPC 2 (targeting) VPC Peering VPC Peering ephemeral cluster ユーザのセグメント情報を書き込み 全てのログ
  18. 18. http://www.slideshare.net/repeatedly/fluentd-unified-logging-layer-at-fossasia
  19. 19. http://www.slideshare.net/repeatedly/fluentd-unified-logging-layer-at-fossasia
  20. 20. シンプルなストリーム処理 in_forwardで受け入れたレコード out_exec_filterで加工 {id: "hoge", segment: "seg1", created: 1426406962, ...} DynamoDBテーブルへ {id: "hoge", url: "http://fuga.com/kuke", user_agent: ..} {id: "hoge", url: "http://hoge.com/a", user_agent: ..} if (domain(url) == "fuga.com") seg = "seg1"
  21. 21. <match hoge.log> type exec_filter command ./our/special/filter/command buffer_type file buffer_path /path/to/ephemeral/disk/hoge </match> ! <match filtered.hoge.log> type dynamodb dynamo_db_table our_targeting_table buffer_type file buffer_path /path/to/ephemeral/disk/filtered ... <secondary> type s3 s3_bucket your-bucket s3_region ap-northeast-1 s3_object_key_format ... buffer_type file buffer_path /path/to/ephemeral/disk/filtered.secondary ... </secondary> </match> in_forwardでおくられてきた ログをうけとり、フィルターする filterしたログをDynamoDBに書き込む batchWriteItemを利用 もし書き込みが失敗したらs3へ 書ききれてませんが、s3への転送もしてます
  22. 22. <match hoge.log> type exec_filter command ./our/special/filter/command buffer_type file buffer_path /path/to/ephemeral/disk/hoge </match> ! <match filtered.hoge.log> type dynamodb dynamo_db_table our_targeting_table buffer_type file buffer_path /path/to/ephemeral/disk/filtered ... <secondary> type s3 s3_bucket your-bucket s3_region ap-northeast-1 s3_object_key_format ... buffer_type file buffer_path /path/to/ephemeral/disk/filtered.secondary ... </secondary> </match> バッファは全てファイル ephemeral diskに
  23. 23. EventStreamノードの運用 • ノードを作り直す場合にはforward側からフェイルしたノー ドを外し、全ての転送が終わったら落とす • Output先を詰まらせないこと。fluentdにバッファをなる べく貯めないことが望ましい。定常的にバッファが貯まる ようなら改善が必要。 • バッファがたまってしまった場合は原因を特定して詰まり を解消した上で、強制的にflush • $ pkill -USR1 -f fluentd
  24. 24. ストリーム処理における状態 プロセッサ データ
  25. 25. ストリーム処理における状態 プロセッサ id: 1 k: 2 データ あるidがk: 1を満たしていたら通したい
  26. 26. ストリーム処理における状態 プロセッサ id: 1 k: 2 データ NG あるidがk: 1を満たしていたら通したい
  27. 27. ストリーム処理における状態 プロセッサ データ あるidがk: 1を満たしていたら通したい
  28. 28. ストリーム処理における状態 プロセッサ データ id: 1 k: 1 あるidがk: 1を満たしていたら通したい
  29. 29. ストリーム処理における状態 プロセッサ データ id: 1 k: 1 OK! あるidがk: 1を満たしていたら通したい
  30. 30. ストリーム処理における状態 プロセッサ データ id: 1 k: 1 プロセッサにとどまる 時間は限りなく短い あるidがk: 1を満たしていたら通したい
  31. 31. 留めるデータが増えるケース プロセッサ id: 1 k: 2 データ あるidがk: 1とk: 2両方を満たしていたら通したい
  32. 32. プロセッサ id: 1 k: 2 データ stay あるidがk: 1とk: 2両方を満たしていたら通したい 留めるデータが増えるケース
  33. 33. プロセッサ id: 1 k: 3 id: 1 k: 2 id: 1 k: 1 データ 条件がくるまで 滞留させる必要がある あるidがk: 1とk: 2両方を満たしていたら通したい 留めるデータが増えるケース
  34. 34. プロセッサ id: 1 v: ok データ 条件をみたしたのでOK あるidがk: 1とk: 2両方を満たしていたら通したい 留めるデータが増えるケース
  35. 35. ストリーム処理における状態 プロセッサ id: 1 k: 3 id: 1 k: 2 id: 1 k: 1 データ 条件がくるまで 滞留させる必要がある 対象とする時間の幅(window)が長くなれば なるほど多くのデータをストリーム処理可能 な場所に保持する必要がある。データの流量 が増えるとそれだけ多くのリソース(RAM 等)が必要になる。 あるidがk: 1とk: 2両方を満たしていたら通したい
  36. 36. 行動ターゲティングの課題 (再掲) • なるべく速く書き込みたい。ユーザが何かをみたら、 すぐにターゲティング可能な状態にしてほしい。反 映が速ければ速いほどいい。 • 案件や対象ユーザが増えても、システム全体が問題 なくスケールすること • 読み込みが安定して低レイテンシであること。でき れば5ms以内。
  37. 37. いろいろ試した結果 • シンプルなmap処理のみリアルタイムに • (30日前にページAをみた and さっきページBをみ た)というセグメントにも対応しなければいけなかっ た・・。のでバッチも併用することに。 • 結果横に並べればシンプルなmap処理についてはス ケールする構成になったので良かった
  38. 38. ELB EC2 EC2 EC2 EC2 request EC2 S3 DynamoDB EMR ELB EC2 EC2 EC2 EC2 http api fluentd fluentd (aggregator) out_exec_filter out_dynamodb servlet (scala) dynamic-dynamo EC2 Growth Forecast EC2 EC2 VPC 1 VPC 1 VPC 2 (targeting) VPC Peering VPC Peering ephemeral cluster EMRでDynamoDBとS3からデータ抽出 再集計してDynamoDBへ書き込み
  39. 39. EMR / Hive • Amazon Hadoop 2.4.0, Hive 0.13.1, core: m1.xlarge * 30, task: c3かr3系統をspot instanceで。専用のSecurity Group を用意。基本的にRCFileで扱う。 • 200クエリ / 日。1日1クラスタ立ち上げて、ひたすらそこに投 げている。DynamoDBとs3からデータを読み込み、集計し、s3 に書き出している。使うHiveクエリは管理ツールから自動生成 or リポジトリにコミットしてJenkinsからs3に上げている。 • アドホックに使う場合には都度別クラスタを立ち上げている。 分析者も手元からThrift経由で。
  40. 40. SET dynamodb.throughput.read.percent=0.8; ! CREATE EXTERNAL TABLE IF NOT EXISTS users ( id string, seg string, created bigint ) stored as rcfile location 's3://path/to/my/user/table'; ! CREATE EXTERNAL TABLE if not exists users_from_dynamodb ( id string, seg string, created bigint) STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' TBLPROPERTIES ( "hive.jdbc.update.on.duplicate" = "true", "dynamodb.table.name" = "our_special_user_table_name", "dynamodb.column.mapping" = "id:id,seg:seg,created:created"); ! INSERT OVERWRITE TABLE users SELECT * FROM users_from_dynamodb; DynamoDBのthroughputをどれくらい使うか DynamoDBカラムとHiveテーブルの カラム対応関係 DynamoDBから全データを 抽出してs3に書き込み
  41. 41. EMRの利点と課題 • 利点 • Hadoopのバージョンアップなど、EMR側がやってくれるので楽 • 潰して、立ち上げなおして、が簡単にできる • bootstrapを工夫すれば様々なHadoop関連ミドルウェアを手軽に試せる • https://github.com/awslabs/emr-bootstrap-actions • 課題 • クラスタ立ち上げは時間がかかる • ジョブスケジューリングは自前で頑張る必要あり • EMRコマンドのデバッグには極論EMRを立ち上げるしか無い
  42. 42. TODO このへんで水を飲む
  43. 43. 行動ターゲティングの課題 (再掲) • なるべく速く書き込みたい。ユーザが何かをみたら、 すぐにターゲティング可能な状態にしてほしい。反 映が速ければ速いほどいい。 • 案件や対象ユーザが増えても、システム全体が問題 なくスケールすること • 読み込みが安定して低レイテンシであること。でき れば5ms以内。
  44. 44. DynamoDB、最高です • ご存知フルマネージドNoSQL DB on AWS • 2年半ほど継続して利用。AWSを使っていて最も選 んでよかったと思っているデータストア。 • 30億レコード入っている。1リクエスト3msで返る。 しかも1度もダウンしたことがない。
  45. 45. 「DynamoDBからの読み込 み遅いんですけど・・・」 「(;・ ・)?」
  46. 46. ELB EC2 EC2 EC2 EC2 request EC2 S3 DynamoDB EMR ELB EC2 EC2 EC2 EC2 http api fluentd fluentd (aggregator) out_exec_filter out_dynamodb servlet (scala) dynamic-dynamo EC2 Growth Forecast EC2 EC2 VPC 1 VPC 1 VPC 2 (targeting) VPC Peering VPC Peering ephemeral cluster 配信サーバからセグメントデータを読み込み
  47. 47. apache (prefork) + PHP apacherequest DynamoDB
  48. 48. apache (prefork) + PHP apacherequest Process DynamoDB
  49. 49. apache (prefork) + PHP apacherequest Process DynamoDB 新規コネクション ( 10ms)
  50. 50. apache (prefork) + PHP apacherequest Process DynamoDB GetItem
  51. 51. apache (prefork) + PHP apache Process DynamoDB response
  52. 52. apache (prefork) + PHP apache DynamoDB response
  53. 53. apache (prefork) + PHP apache DynamoDB response リクエストからレスポンスまで 30ms
  54. 54. 秒間リクエスト数が増えた時 apache DynamoDB
  55. 55. 秒間リクエスト数が増えた時 apache request Process DynamoDB requestrequestrequestrequestrequestrequestrequestrequestrequestrequestrequestrequest Process Process Process 待ちプロセスが増える = LAが上がる
  56. 56. • PHP製のapiをScalaで再実装。Servletを利用。 • DynamoDBへのコネクションをプールするように • responseが早くなり、同時接続数が増えすぎるこ となく、安定して稼働
  57. 57. fluentd「DynamoDB つまって書けないんで すけど」 私「( ゚д゚)」
  58. 58. ELB EC2 EC2 EC2 EC2 request EC2 S3 DynamoDB EMR ELB EC2 EC2 EC2 EC2 http api fluentd fluentd (aggregator) out_exec_filter out_dynamodb servlet (scala) dynamic-dynamo EC2 Growth Forecast EC2 EC2 VPC 1 VPC 1 VPC 2 (targeting) VPC Peering VPC Peering ephemeral cluster out_exec_filterでログを加工 DynamoDBに書き込み
  59. 59. 書き込む量が増えてWrite capacityが 足りなくなった! • 勝手にスケールするようにしよう!ということで dynamic-dynamodbの導入
  60. 60. 結果
  61. 61. Write Capacity Read Capacity Query Latency
  62. 62. テーブル設計イメージ user_id String (hash key) segment String (range key) created Number … hoge seg1 1426406962 hoge seg2 1426406962 fuga seg1 1426406962 kuke seg1 1426406962
  63. 63. DynamoDB Tips • 1Itemあたりのバイト数を小さくする(1KBを超え ないように • hot keyを作らないようにする(hash keyに同じID が大量に存在する状態にしないようにする • DynamoDB - EC2の新規コネクションはそれなり にコストが高い( 10ms)ので、コネクションを プールする(つながれば安定して速い 参考: http://www.slideshare.net/AmazonWebServicesJapan/aws-black-belt-tech-amazon-dynamodb
  64. 64. 若手解析者「すずけんさん、Hive遅 いんすけど何とかならないっすか?」 私「(́・ω・`)」
  65. 65. アドホックな データ分析
  66. 66. 部分的にBigQueryを利用 • EC2 -> S3 -> SQS -> EC2(worker) -> GCS • アドホックな分析用はこちらに移行中 https://cloud.google.com/bigquery/?hl=ja
  67. 67. BigQuery • いいところ • クラスタのメンテしなくていい。(Hadoopクラス タの面倒見なくていいし)。速い。コンソールも 最初からついてる。Google Appsと連携できる。 • 使いづらい所 • 権限周り。まだAWSと比べて細かい制御が難しそ う。UDFが(まだ)使えない。
  68. 68. 現状の使い分け • Large Batch: EMR + Hive • Short Batch: BigQuery • Stream Processing: Fluentd + out_exec_filter 参考: http://www.slideshare.net/tagomoris/hcj2014-sql
  69. 69. データと組織
  70. 70. プロダクトオーナーシップ • インフラも、データも、サービスも、営業も • 「このデータを取れるようにしたいだけど?」に対 して、全方面に答えられる必要がある。ログに10 バイト情報を増やすだけで、10バイト 250億だ け月に扱う量が増える。帯域、ディスク、関連する コストが増える。それらに見合うだけの価値があと から出せるのかを考える必要がある。
  71. 71. –Amazon’s Leadership PrinciplesのOwnershipより リーダーにはオーナーシップが必要です。リー ダーは長期的な視野で考え、短期的な結果のた めに、長期的な価値を犠牲にしません。リーダー は自分のチームだけでなく、会社全体のために 行動します。リーダーは「それは私の仕事では ありません」とは決して口にしません。
  72. 72. cf. Amazon • Amazon Kinesis Developer Managerの Goさんの話 • AmazonのLeadership PrinciplesのOwnership について • インフラチームもサービ スチームもOwnershipを
  73. 73. ビジネス的な改善の重視 • VOYAGE GROUPのエンジニアは技術的なレビュー を受ける。人事評価も影響する。 • 現場のエンジニアでもプロダクトの数値を「見え る」ようにすることを意識させられる。 • データをうまく扱う環境をつくること -> ビジネス を改善すること 参考: http://gihyo.jp/design/serial/01/creative/0006
  74. 74. まとめ
  75. 75. 普通のことを普通にやる • パフォーマンスも、運用も、コストも。データの配 置も、必要なところだけ、必要なことを。データや トラフィックが増えても、普通のことを普通にやる。
  76. 76. エンジニア採用中です! https://voyagegroup.com/adtechunit/

×