巨大レガシーシステムのパフォーマンスチューニング

森廣隆行氏:それでは、「タウンワーク90万原稿の掲載を支えるレガシーバッチパフォーマンスチューニング」と題しまして、発表させていただきます。本日はよろしくお願いいたします。

まず自己紹介になります。

先ほどご紹介にあずかりました、森廣隆行と申します。経歴といたしましては、2006年に新入社員としてSIerに入りまして、主に金融系・カード系の業務基幹システムの運用・保守・開発を5年行いました。その後、ナビアプリ会社に2010年に入社しまして、自社アプリのサーバーサイド及びフロントエンドの開発を6年やったあとに、いまのリクルートテクノロジーズに入社いたしました。

入社してからは、フロム・エー ナビの運用・保守・開発を2年やったあと、いまのメインとなっているリクルートジョブズ全域の領域アーキテクトとして働いております。主な役割としては先ほど言ったとおり、リクルートジョブズ全体のサーバーサイドのJavaと、フロントエンドのJavaScriptの責任者をしています。最近ではGoや、React/Reduxなどもやっています。

では、本日の内容です。

さっそくですが、去年見られた方もいらっしゃるかと思いますが、高橋陽太郎さんが去年登壇してお話しした「タウンワークをドライブさせるためになんちゃってアジャイルをやめた話」の、技術側の話になります。

注意点ですけど、概要を読まれた方はたぶん大丈夫だと思うんですが、一応……本セッションはレガシーコードにまみれた世界での社員エンジニアの奮闘記です。新技術とか、そういうキラキラしたものはまったくございません。古くから使われてる手法ばっかり使ったものになりますので、何卒ご了承ください。あとスライドは後日公開いたしますので、そちらを見ていただければなと思います。

「当たり前品質」が求められる入稿システム

まずはじめに、リクルートのいつものリボンモデルになります。

リクルートジョブズはクライアントとカスタマーに対して、クライアントからいただいた求人情報をタウンワークやフロム・エー ナビ、とらばーゆ、はたらいくなどのメディアに掲載したのち、カスタマーに認知していただき、求人をマッチングするというサービスを行っております。

本日はこのリボンモデルでいう、「受注」と「掲載」というところのバッチパフォーマンスチューニングの話をさせていただきます。

背景になります。

先ほど言った受注と掲載の図をわかりやすく描くと(スライドの)下のほうになります。営業とクライアントで商談した結果、掲載していただくことになった場合に使う、入稿システムの話になります。

この入稿システムはリボンモデルの根幹を支える部分であって、これがないとビジネスが成り立たないため、必然的に「当たり前の品質」となって求められてしまいます。そういう現状がございます。

営業のほうで「新規開発だ!」となった場合、新規関係では商品の追加や掲載の追加が起こるんですけども、「当たり前品質」というのがやっぱり優先されます。開発としては既存の処理に手を加えるのではなく、新規追加というディフェンシブな対応がよくとられることがあります。そんな中でやっていた結果どうなったかというと……。

(会場笑)

ちょっと見にくいですが、これがシステム図になります(笑)。詳細はぼかしてあるんですが、見にくいので(各システムを)書くとですね、こんな感じです。

左上に入稿システムがありつつ、真ん中のほうにフロム・エー ナビとタウンワークがあります。あと、書いていませんが、四角に囲われているのが各システムで、そこを大量につないでいる線が入っているという状態になってしまっています。

個別最適化ではなく、フローの全体最適化を実施

この状況下において、近年掲載数がオリンピック需要もあり増えているという現状がありつつ、掲載の処理自体に急速な性能劣化が発生してしまうということが起こりました。

ただ、それは見えていなかったのかと言われると、実際は見えていてですね。

入稿システム単体での対応はちょこちょこと行っていたんですけれども、やっぱり掲載数の増加には耐えられず、どうしようもないという現状があります。

こういう状況になった場合、リプレイスとかリビルドという手法がよくとられると思いますが、これを行ってしまうと1年、2年では済まずに開発期間が長期になってしまって、凍結を行わなければいけないということになります。そうなってしまうとやっぱり、タウンワークとして売上のほうが下がってしまうというところがありますので、機会損失が大きくて現実的ではない、ということになりました。

今回はどういうかたちで対応したかというと、従来の「担当システム」という個別最適化ではなくて、「原稿入稿処理フロー」という全体の最適化を行いました。

ただ、チームを集めて横断的にやったとしても先ほどのように根本的な解決にはならず、チームの壁というものを潰して対応しなければいけないということで、各チーム・各インフラの企画も巻き込んでのチーム編成をして、今回の対応を行いました。

実施したこと

続きまして、実施内容になります。先ほどの原稿情報入稿フローを図に描くと、このようになっています。

クライアントからご入稿いただいた原稿を、入稿システムのほうでまず受け取り、それを日に4回ほどタウンワークに転載する仕組みになっています。

ここで問題になっているのが、この3つです。

まず原稿システムのほうで、クライアントから入稿されたデータをタウンワークに転載する前のところの処理、及び、原稿システムからタウンワークに転載するところの処理です。あと、タウンワークでは一覧にSolrを使っているんですけれども、そこの部分に反映するところの処理。この3つが問題になっていました。

業務とシステムの不一致

まず1つ目、入稿処理の話をします。

問題として何があったかというと、業務とシステムの不一致です。先ほどは業務フローのかたちで見せたんですが、役割的なところで言うと、この連携部分……業務と入稿システムの連携になります。

何が起きているかというと、タウンワークはご存知のとおりフリーペーパーを出しております。これには、月曜日の朝に掲載するというものがございまして、それを実現するために毎週金曜日の夜に入稿締めがあり、そこから締めたものを印刷して、全国に配送して朝に掲載しています。

このフローに引きずられてWeb側も、日曜の夜に、月曜の朝に掲載するために一気に原稿を処理してWebに載せなければいけないというものがあります。この部分ですね、1週間まとめて処理をしなければいけないことが、今回問題になっておりました。

この部分を詳細化すると、このようになっています。

原稿処理といってもさまざまあります。新規掲載、及び停止・修正という3つの処理があるんですけれども、今回の場合は1週間分の新規入稿という部分が多くなってしまったことが問題になっておりました。

そこで、この処理の部分を詳細に落とし込んだところ、編集処理と呼ばれる、画像の加工や印刷をするためのPDFを出すといったコード変換などの処理と、連携テーブルにデータを叩き込むかたちの反映処理という、2つに分けられました。

これをどうしたかというと、クライアントから入稿されたタイミングで、もう処理しちゃおうというかたちで、今回変更をかけております。ただ、これにしたことによって何が起こるかというと、金曜日までにクライアントさんは、1回入稿してから修正を加えられると思いますが、処理的には増えるんだけれども処理を分散することによって、日常の一括処理が軽くなる。そのために今回、このようなかたちをとりました。

結果がこのようになります。

基本的に処理量は増えているんですけども、日曜日の夜というタイミングの処理量を分散することによって、速くしております。

システム間連携の不備

続きまして、問題の2つ目です。

この入稿システムとタウンワークの連携の部分ですね。ここで何が問題になっていたかというと、システム間の連携の不備になります。

ここで問題となってくるのが、原稿入稿開発チームとタウンワークの開発チームとで、チームが分かれていることです。

コミュニケーションをとっているとはいえ、そんなに仲がよくない……あ、言っちゃいましたね。

(会場笑)

まぁ、そういうことがあります(笑)。そして先ほど言ったとおり、反映処理というのは、新規入稿や停止・修正というかたちで分かれているんですけれども、タウンワークチームにこの情報が渡されていなかったということが、今回わかりました。

これによってどうなっていたかというと、基本的にタウンワークでやっていた処理は、連携テーブルに入っているデータを原稿テーブルの中から消して、また再投入するというかたちをとっておりました。

SQLも2回、ついでにロックもかけまくりで、すごく時間がかかっていました。

今回、データをちゃんと連携するというコミュニケーションをとることによって、タウンワークチームでも新規入稿と停止・修正の処理を分けて、新規入稿に関してはインサート、停止に関してはアップデートですね。

修正に関してはアップデートでもよかったんですけれども、どこを直したかというデータを渡してもらうのが大変だったので、ここだけはデリート・インサートというかたちで分割をすることによって、高速化しております。

また、もう1つ問題がありまして、仲が悪いのもあるんですけれども、マスターチェックがあるため、連携テーブルの削除という処理があります。

これをよくよく見てみたら、両方からやっている。無駄な処理がいっぱいあったので、そこを削減することによって高速化を行いました。

結果、どうなったかというと、こんな感じです。

入稿システム側に削除とマスターチェックのほうを寄せて、タウンワークのほうは新規入稿と停止・修正というかたちで処理をして、チーム間での役割分担を明確にし、情報共有を密にすることで、高速化を行いました。