关于制作排行榜数据时的AWS服务选择

我是Zom。

该文章是日全日住宅的圣诞日历第1天的第23天的文章。

由于今年即将结束,我想写一下我负责的Web应用程序。通常,我会在圣诞倒数日之前,写关于我一直感兴趣的主题的调查验证内容。

Webアプリケーションにおける技術選定という工程は、そのときの要件、リソース(時間や人、金)、会社・組織・あるいはレガシーなシステムとのしがらみといった変数によって大きく変化します。
そのためQiitaなどで検索してもなかなか参考になる記事や考え方が見つからず、どうしたものかなぁと思ったので、このときの設計や技術選定の過程について書いてみようと思います。初めてこういったことをする人の参考になればいいな、と思います

なお、このプロダクトの作成時期は2019年の3月頃です。
また私の部署ではAWSを利用した環境が主なのでAWSのサービスで考えました。

要件

    • 駅/市区町村のランキングを表示する

駅数は2018年4月1日時点で9516駅(5/29(火)日本中の駅の数、全部でいくつ? 【駅DB2018年度、整備完了いたしました!】 | ナビットブログ調べ)
市区町村数は2019年時点で1724市区町村(市区町村数を調べる | 政府統計の総合窓口調べ)
つまり合計1万超のデータを用意する

もちろん本当は弊社所有のデータで計算していますが、Qiitaに載せていいのか分からないので参考値として↑を挙げさせていただきました

ランキングの元データは3ヶ月分のデータを利用すること

具体的に3ヶ月分の何なのか、はロジックに関するので非公開とさせてください

前置條件(應達到的目標)

    • 技術選定は自由

その代わりに使い慣れたレガシーなシステムをなるべく使わないようにすること
古いレールに乗らない、次のレールを作るつもりでやること

人員は1人、納期はなる早であること

这个前提没有特殊要求,但是当时的上司(或类似的人)提出了这个要求。
可以自由地做,希望能成为后辈的榜样,这就是要求。
实际上,这个要求有更加温和的含义,但是在公开场合写作时会变成这个样子。

最初に考えたこと

前提条件を抜きに一旦考えてみます。

データストアを何にするか

    • S3?

 

    • RDB(RDS)?

 

    KVS(ElastiCache or DynamoDB)?

如何收集数据

    • 既存のログを集計する?

 

    新規に専用のデータを取り始める?

如何进行数据汇总处理

    • EC2でcron?

 

    • Lambda?

 

    • AWS Batch?

 

    AWS ECS?

在RDB中进行实时计算,例如使用ORDER BY等功能,可以避免额外处理,也可以考虑使用数据存储完成整个过程。

上記のようなことが頭の中をよぎります。
他にもあるかもしれませんが、当時の自分が最初に思い浮かんだ選択肢はこんなところです。
ここからサイトでのレスポンス速度、既存の構成との兼ね合い、納期、拡張性(他のページでの利用しやすさ)、保守性(運用の楽さ)、前提条件などから最適解を見つけます。

選擇

尽管有自由,但是金钱和交货期还是不能忽视。因此有些选项会被排除在外。

开始获取专用数据
排行榜的原始数据使用三个月的数据

在一个诚实,自由的环境中,我觉得有机会亲自做日志设计!但是因为要显示三个月的数据,这将导致从发布到排名显示需要再等待三个月。这与我们提前设定的“尽快”条件相违背,因此被拒绝了。

关系型数据库

我认为,对于某些人来说,RDB可能根本不是一个很好的选择。我考虑过不太充分地利用RDB的关系部分,而仅仅使用键值存储就足够了。此外,由于公司内部的一些限制,我也找不到在我们已经使用的数据库上创建新表的积极理由。

在EC2上配置cron

これは社内では実績がある作り、バッチ用インスタンスなるものが存在します。なのでそこで開発すればリリース速度はおそらく一番早く、納期重視だったらこの選択肢を選んでいたことでしょう。
しかしレールが古く私自身にとっても学びが少ない作り方になってしまうので採用しませんでした。

Lambda
拉姆达 (lā mǔ dá)

ランキングの集計処理に関して言うと、真っ先に思い浮かんだのはLambdaでした。
そのつもりでデータ設計などをして試しにデータを集計する処理などを書いたりして検証を始めたのですが、3ヶ月という膨大なデータ量がLambdaの制限である15分の壁をクリアできないということが発覚しました。
たしか1ヶ月分のデータでも15分の壁を突破できなかったと記憶しています。
検証はしていませんがメモリ量(CPU)を多く割り当てれば行けた可能性はあります。ただ、メモリ量を増やしたところでデータ量次第でさらにメモリを必要とする、安定稼働しないリスクがあるということになりますので別の方法を考えておくべきだと考えました。

※データ量がネックになっているので、あれば例えば10日分のデータなど細かい単位で実行し、中間データみたいなものを作るという手法も検討しました。
ただそうなると中間データを生成するバッチ処理と最終的なデータを生成するバッチ処理の2つが必要になります。
この場合前後関係ができてしまい、順番を考慮する必要があるなど要件に対して管理コストが高くなってしまうのでは?ということで却下しました。

AWS批处理

因为Lambda似乎不符合选择,所以我也考虑了从未使用过的AWS Batch,但是我感觉它对我想做的事情来说功能过于复杂。
当时我参考了一篇文章,文章标题是《了解AWS Batch的基本概念@pottava》。

これがマネージドされると僕らは何がうれしいのか

本来やりたい、ジョブの実行依頼(submit)と実処理だけを考えればよくなる
クラスタ全体で利用可能なリソースの把握、過不足に応じたその調整が不要3に
前処理、集約処理、後処理といった流れのある処理も基盤側に制御を移譲できる
依頼者や状況に応じた優先的リソース配分が容易に実現できる
CPU / GPU でそれぞれクラスタを作り、前処理 CPU、本処理 GPU なども簡単
クラスタごとに可用性、パフォーマンス、コストのバランスが定義しやすい
Docker イメージにさえしてしまえばどんな処理も AWS Batch に乗せられる
すでにデータ分析パイプラインの定義があれば移行しやすい(かもしれない)

上記記事より一部引用

3ヶ月分のデータがサクッと集計できるのであれば 前処理、集約処理、後処理といった流れのある処理 も不要ですし、 状況に応じた優先的リソース配分 や CPU / GPU でそれぞれクラスタを作り、前処理 CPU、本処理 GPU なども簡単 といった、そんなことをせずに済むのです。

因此,AWS Batch也被排除在选择范围之外。

采用的物品

    • 既存のログを

 

    • AWS ECSで集計し

 

    KVS(Redis(ElastiCache)のSortedSets)に入れる

这是一个结构。

ここからは今まで以上に既存のシステム構成によるので汎用性のない話になります。

现有的日志

既存のログというのがS3上に格納されていました。
S3上にあるデータを集計するといえばAWS Athenaですね!

これをAWS ECSで集計します。

AWS ECS

ECSはDockerコンテナアプリケーションをAWS上で実行できるサービスです。またFargateを使えばサーバレスで実行できるのでサーバの管理コストも減らせます。

プログラムは個人的に好きなRubyで書きAWS SDKを使ってAthenaの実行をしました。データベースの作成からテーブルの作成など、すべてSQLライクに書けるので多くのエンジニアでもとっつきやすいのではないかと思います。
が、S3のログの内容からデータ型の設定がうまく行かないとか、思ったよりいろんなポリシーを必要としてIAM周りをバコッと食わせる必要があるとか、サービス間の連携の部分でのハマり事はあるかもしれません。

プログラムからRedisに接続する際の接続情報をセキュアに管理したほうが良いよね、となったときはParameterStoreを使うことで難なく実現できました。便利。

肝心の定期実行はCloudWatchEventsのcron式で実現可能です。
ハマりどころとしては、UTCの時間であることや、通常のLinuxのcronとちょっとだけ構文が異なったり、CloudWatchEvents独自の記法があるのが少しだけある程度です。

Redis 的 SortedSets

这个也特别方便。曾经在切换从使用 Memcache 到 Redis 时,看到了 Redis 2.0.3 文档中关于排序集合类型的介绍,当时就有一种”总有一天我会用上它的”的心情,现在终于到了用它的时刻,充满了喜悦。

上記の日本語ドキュメントは2.0.3時点のものなので存在していませんが、
zrevrangebyscoreが今回最高に使えました。
スコアの高い順にソートして返してくれる、上限下限も設定できるのでスコアによる足切りもできちゃうし、offsetとcountがあるのでランキングのページング機能もお手の物。スコアも返せちゃうので同点だったときにちょっと入れ替えようか、なんてときもアプリケーションで制御可能です。(同点だったときのデフォルトはmemberのASCIIコード順になるはず)

最終的に利用したAWSのサービス

    • ログ置き場としてS3

 

    • 集計のメイン処理としてAthena

 

    • 実行環境としてECS

 

    • コンテナイメージ管理としてECR

 

    • ECS起動&ログ出力のためにCloudWatch(Events)

 

    データの保存先としてElastiCache

变成了这样。

結びに

今回は様々な事情からこのような構成になりましたが、LambdaやAWS Batchを使う可能性も全然ありえたとは思います。例えばLambdaのところで触れた中間データも、他のアプリケーションで使い回すことがあるなどの要件や展望があれば採用されていたと思います。
また今回は自分の想定の中にありませんでしたが、多くのWebサービスでも使われているであろうGoogleAnalyticsから集計するという手法もあったのではないかと思います。

我希望能够充分利用AWS服务,以便能够方便、安全且稳定地提供价值。

广告
将在 10 秒后关闭
bannerAds