見出し画像

バッチ処理と歩んだ3年間

はじめに

本記事は、ストックマーク Advent Calendar 2021の11日目(に出すはずだっった)の記事です。日付を1週間勘違いするという社会人にあるまじき初歩的なミスをお許しください。

こんにちは、ストックマークでテックリードをしている岩谷です。

本記事では、Anewsというサービスの中で、機械学習を伴う重めのバッチ処理をどのように改善してきたか、1つの事例としてご紹介できればと思います。ソフトウェア開発・運用の観点でのお話で、機械学習の込み入った話には言及しません。

Anewsについては、テックブログでサービスや機械学習の裏側をご紹介していますので、参照いただけると幸いです。

出会い

私が入社したのは2018年9月で、当時まだ社員は10人程度で何もかもが混沌としている時代でした。バッチ処理はCTOの有馬と現エンジニアリングマネージャーの谷本の2人によってほとんど開発が行われていたのですが、2人ともWebサービス開発のキャリアがあったわけでもなく、時間もお金もノウハウも無い、いつ会社が無くなるかわからない作るか売るかという緊迫した日々の中で作られたシステムは、大学生が研究で書いたスクリプトをつなぎ合わせたカオスの塊のような状態でした。

再実行性

いくつかの機能開発を経て、システムの開発運用の全体像が掴めてきた頃、1番危ういと思ったのが、バッチの再実行でした。当時は1000弱のお客様環境のニュースレコメンデーションを、1お客様環境1JOBとして8並列で走らせており、1JOBの中にも血と汗と涙の詰まった様々な処理が直列で詰め込まれていました。JOBがこけると、頭から再処理することができず、落ちた場所の調査と、途中からの実行を一つ一つ手作業で実施しなければならない状態でした。1JOBだけでも大変な再実行作業を、時には数十、数百という処理を人の手で起動していました。

我々が大変なことより、対応に時間がかかるとお客様にご不便をかけるのが最大の問題で、いかに再実行性を上げるかにまず着手しました。

改善にあたってのポイントは大きく以下の3つでした。

  1. JOBの途中から手動実行しなければならない状態を解消したい

  2. たくさんあるJOBを1つ1つ実行する状態を解消したい

  3. 朝の利用ピーク前にニュース配信するために、あまり再実行に時間をかけられない

各JOB単位で、冪等性を持たせることで1, 2は解消していきました。とにかく様々な処理が直列につながっていたので、愚直に1つずつの処理の役割とデータのIN-OUTを整理していき、頭から再実行しても同じ結果になり、データが2重で作成されないように処理を改善していきました。

3については、JOB全体およびJOBの中で正常に終わった処理は可能な限り再実行されないよう、状態管理なども駆使し、こちらも愚直に解決していきました。

最終的に、全体のBatch処理を起動する1ボタンで再実行が行える状態になりました。

処理速度

次に手をかけたのが処理速度です。0時〜5時の約5時間かかっており、朝の配信まで余裕が無く、お客様環境が増えていけばいずれ朝の配信(6時〜8時ごろ)に間に合わなくなることは明白でした。

まずは問題の特定です。当然、処理時間が簡単に計測できるモニタリングやロギングといった裕福な仕組みは皆無だったので、JOBの所々にログを差し込み、時間のかかっている処理の切り分けを進めていきました。ある程度範囲が絞れたら、テスト環境でデータ量などを変えつつ原因を特定していきました。

様々細かな改善もあったのですが、最も支配的だったのは、形態素解析の時間と、配列型による大量データ操作でした。(バッチ処理は全てPython)

形態素解析の最大の問題は、同じデータに対して何回も形態素解析を行っている点でした。とにかく機能を追加追加で最適化など全く行われていない状態だったので、1JOBの中で1度形態素解析したデータは使い回すようにし、最終的には形態素解析済データを事前に作成保存しておき、各JOBからは作成済のデータを参照することで処理の無駄を最小化していきました。

配列型による大量データ操作は、扱う記事量のオーダーが日に数万〜数十万で、2重forループにした時点で処理量オーダが百億レベルになってしまうことが問題でした。開発時は問題にならなかったが、サービスの進化・データ量の増加とともに顕在化する類です。特定さえできれば解決は簡単で、とにかくlistをdictに変えてインデックスが効くようにしていきました。現在ではrubyやjavascriptも書いていますが、インデックスの効かないデータ構造を見るといつもドキドキしてしまいます

最終的に処理時間は3分の1程度まで改善され、平和が訪れました。

新Anewsに生まれ変わり、現在

この後私はAnewsの開発を離れている間に、新Anewsへのリプレイスが行われました。プロフェッショナルなメンバーが増えたこと、また1から作り直すことで全体の処理が最適化されて開発できたこともあり、お客様の数は大きく増えたにもかかわらず、1時間程度でバッチ処理が完了するようになっていました。

それでもサービスの成長とともに今の仕組みでの限界が近づいてきており、最近ではさらなる高並列化による高速化や、RDB負荷がかなり高くなってきている状態を解消するためにIO負荷の最適化なども少しづつ取り組んでいます。

本当はもう少し技術的に参考にしていただけそうな最近の話も書きたかったのですが、昔の話を書き出したら懐かしくて分量が多くなってしまったので、またテックブログ等で発信できればと思います。特にスタートアップのような環境では、リソースの制約や事業優先により技術負債が積み上がるのはあるあるだと思うので、「わかる」「へー」などと思っていただけたなら幸いです。

宣伝

このままでは過去の恥をさらすだけの記事になってしまうので宣伝をして終わりたいと思います。

ストックマークでは一緒に働くメンバーを絶賛募集中です!Anews開発メンバーも募集していますので、ご興味あればカジュアル面談からでも、是非ご連絡ください!



この記事が気に入ったらサポートをしてみませんか?