LINE株式会社は、2023年10月1日にLINEヤフー株式会社になりました。LINEヤフー株式会社の新しいブログはこちらです。 LINEヤフー Tech Blog

20億req/dayを受けるレコメンドサービスの裏話。Smart Channelが直面する問題とその対策 

LINE株式会社およびヤフー株式会社は、2022年11月17日・18日の2日間にわたり、技術カンファレンス「Tech-Verse 2022」をオンライン(ライブストリーミング形式)にて開催しました。特別連載企画「Tech-Verse 2022 アフターインタビュー」では、発表内容をさらに深掘りし、発表では触れられなかった内容や裏話について登壇者たちにインタビューします。今回の対象セッションは「20億req/dayを受けるレコメンドサービスが直面する問題とその対策」です。 

LINEアプリのさまざまな場所にレコメンドを届けるSmart Channelは、日本・タイ・台湾の合計1億6,700万ものユーザーMAU)に向けて、毎日1,600万以上のコンテンツを配信しています。デイリーのリクエスト数は20億を超え、LINEの中でも規模の大きなサービスです。この規模のサービスを運用するうえで直面した困難やその対応策についての秘話を、LINEのCRS Dev teamに所属するSoftware engineerの渡邉直樹(hackmylife)が解説します。 

「突如発生したレスポンス速度の低下」に対応するために 

――今回のインタビューでは「Tech-Verse 2022」のセッションをふまえ、より深掘りした内容を伺います。セッション内では「突如発生したレスポンス速度の低下」の概要とその対応策について解説されていました。mgetの数が爆発的に増加したことの対応策として、フィルターとリミットをかける施策を実施したことを説明されていましたね。 

 セッション内ではその施策の解説のみをしましたが、取り組んだ対応としては実は他にもありました。具体的に言えば、処理の非効率な部分を直すための、大規模なリファクタリングを同時に進めました。たとえば、複数種類のコンテンツのTargetingをfetchして、その結果をマージする処理が挙げられます。かつては逐次処理でfetchしていたのを、並列処理に変えてロジックの最適化を行いました。 

 それ以外に、アイデアとしては挙がったものの実施しなかった施策もあります。セッション内では、ユーザーにレコメンドするコンテンツの種類を、過去にユーザーが行動した結果から作られるTier1と、ユーザーの属性などから作られるTier2に分けて、それらの結果をランダムで取得している旨を解説しました。 

 本当ならば、これらのコンテンツの順位付けを行うほうが、ユーザーにとってより最適なコンテンツを出せる可能性があります。ですが、開発にかけられる時間に制約があったことや、レスポンス速度が遅くなってしまいそうなことから、この案を見送ることに決めました。 

 ユーザーは基本的に、Smart Channelの表示内容を閲覧するためではなく、チャットなど他の機能を利用するためにLINEアプリを開いています。だからこそ素早くコンテンツを表示しなければ、そもそもSmart Channelの存在には気付いてもらえません。サービスの性質上レスポンス速度は重要であり、その速度を下げるわけにはいかなかったことが見送りの理由です。 

 ですが実はちょうど今、レスポンス速度を維持しつつユーザーにより最適なコンテンツをレコメンドするための設計を私たちのチームで考えており、おそらく遠からずリリースされます。今後も改善を続けていくつもりでいます。 

 ――他にセッション内で語られた「Redisの特定のノードにアクセスが集中してしまう問題」についての裏話はありますか? 

セッションではキャッシュを用いた設計を解説しましたが、それ以外にもアイデアとしては挙がったものの採用しなかった案があります。ひとつの情報がひとつのノードにしか存在しないためにこの問題が発生するので、情報をコピーして複数のノードに書き込んでおけば処理を分散できると考えたんです。つまりInformationのシャーディングを検討していました。 

 ですが、設計がややトリッキーになってしまうのと、自分たちの想像よりもキャッシュ導入の効果がはるかに高かったこともあり、キャッシュによって十分に課題を解決できたので、シャーディングは廃案になりました。ただ、このアイデアは後に別の形で活かされています。実はそのネタも「Tech-Verse 2022」で話そうと思っていましたが、持ち時間の都合上、ボツになりました。 

セッションでは語られなかった「Targeting Redisの課題」 

 ――よろしければ、時間の都合でお話できなかった内容を教えていただけますか? 

 これは、Targeting情報を格納するRedisで発生した課題です。当時、このRedisにはトークタブに掲載するための情報が12億アイテム、ホームタブに掲載するための情報が10億アイテム、合計で22億アイテムが格納されており、相当に大きなクラスタになっていました。 

トークタブへのSmart Channel表示機能は日本とタイ、台湾でサービスローンチしていますが、ホームタブへのSmart Channel表示機能は日本でしかサービスローンチしていません。今後、タイや台湾でもサービス展開が予定されていて、、さらにアイテムが増えると想定されていました。そうなるとRedisの容量が不足し、それ以上の情報が格納できなくなってしまうことが危惧されていました。 

Redisクラスタを拡張すればいいと思われるかもしれませんが、すでにそのクラスタはプライマリが48ノード、レプリカが48ノードで合計96ノードという、それなりの規模の構成でした。LINE社内で提供されているRedisクラスタはデフォルトでは96ノードまでしかサポートしていません。そこで、倍の192ノードに拡張した場合に何が起きるか、別途検証する必要が生じました。 

検証作業を社内のDBAに依頼したところ、192ノードにするとノード相互監視のための通信の影響で、レイテンシーが増えることが判明しました。また、過去の実績では48ノードから96ノードに拡張した際に、拡張処理が完了するまでに12時間ほどかかったり、一時的なエラーが発生したりしていました。そのため96ノードから192ノードに拡張する際には、さらに時間がかかりエラーも起きることが想定されたんです。 

また、今後更に拡張が必要になった時、さらに多くのノード、例えば384ノードでのテストをすることを考えると、なかなかテストのコスト大変だなと考えたのと、ノードを増やすことによって、レイテンシー増加などのリスクが高くなると考えられますし今後のメンテナンスが大変になりそうでした。 

私たちが最終的に選んだのは、特定のRedisクラスタを拡張する方針ではなく、アプリケーションレイヤーで複数のRedisクラスタを振り分けるという、Redisクラスタ自体のシャーディングをするという方針でした。ユーザーIDの値をConsistent Hashingして、該当ユーザーの情報を格納・取得するRedisクラスタがどれになるのかを判断する仕組みを作っています。 

この設計にすることで、仮に今後さらにユーザーが増えたとしても、別のRedisクラスタを増設するだけで事足ります。メンテナンスにかかる工数や発生するリスクを最小限にできると考えました。 

災害などの緊急時に情報をなるべく早くユーザーのもとに届けたい 

――次に、セッションで述べられていた「地震」のトピックについて伺います。緊急時に優先度の高いコンテンツをユーザーに届ける​​Prioritized Deliveryの仕組みは、いつ頃にどのような経緯で導入されたものなのでしょうか? 

導入されたのは2020年くらいだと記憶しています。Smart Channelはクライアント側がコンテンツをPull型で取得する構造であるため、もともとは優先度の高いコンテンツをリアルタイムで届ける仕組みがありませんでした。「災害などの緊急時に情報をなるべく早くユーザーのもとに届けたい」という思いから作られたのが​​Prioritized Deliveryでした。災害や人々の命に関わる事態、生活を大きく変えてしまう出来事などが発生した際に、Push型でユーザーへとすぐにコンテンツを届けるための仕組みです。 

――セッション内では、災害時に大量トラフィックが発生してシステム応答ができなかったことの対応策として、サーバーのスケールアウトをした旨が紹介されていました。スケールアウトを行うと可用性が向上する一方で、サーバーの金銭的コストや運用コストが増加しますが、それらのコスト増について何かしらの考慮や対策はされましたか? 

 確かにその通りで、コスト増加とのトレードオフになってしまう側面はありました。ですが、災害時には突発的なアクセススパイクが発生するので、オートスケールなどではスケールアウトが間に合わないんですよね。Prioritized Deliveryは人々の命や生活を守るための機能ですから、ある程度のコスト増加を受け入れてでも、その可用性を担保すべきだと判断しました。 

 LINEはもともと、2011年の東日本大震災をきっかけとして「誰でもいつでも簡単に連絡が取り合えるコミュニケーションサービスを作ろう」という思いから生まれたアプリです。だからこそ、Prioritized Deliveryの機能はLINEの思想にも通じています。

数多くのユーザーの目に触れる機能だからこそのやりがい 

 ――CRS Dev teamにいるからこそ経験できたことはありますか? 

 CRS Dev teamはLINEアプリの中でも特にトラフィックの多いトークタブにサービスを提供しているため、膨大な量のトラフィックをさばく経験ができるのは面白いです。大量アクセスに耐えられるアーキテクチャを考えることや、何かのトラブルが起きた際に対策をすることなどが、エンジニアのキャリアにおいて大きな挑戦になります。 

さらに、Smart Channelはレコメンドの要素が絡むシステムであるため、機械学習に関する処理が組み込まれており、LINE社内の機械学習のチームと協力体制を築いて開発しています。CRS Dev teamに所属していると、そうした機械学習のロジックをサーバーサイドエンジニアも実装できる機会があるのが嬉しいです。このチームにいることで、私自身も機械学習に少し詳しくなりました。 

 ――Smart Channelの開発や運用に携わる醍醐味はどのような点にありますか? 

 数多くのユーザーの目に触れる機能なので、「自分が開発した機能が世の中で使われている」という実感があります。ユーザーの声を直接的にインタビューで聞いたり、SNSでエゴサーチをしてユーザーの意見を見たりして、サービスを改善していけることが楽しいです。 

 それから、Smart ChannelではA/Bテストを頻繁に実施しています。なぜなら、機械学習のロジックを用いてレコメンドを出力することには明確な答えがなく、常に実際の結果をもとに改善を続ける必要があるからです。自分たちの仮説を立てて、その通りの結果が出ることもありますし、仮説とは異なる結果が出ることもあります。その因果関係を探っていくプロセスそのものに、個人的にはやりがいを感じています。 

――渡邉さんのエンジニア個人としての今後の目標を教えてください。 

 私はこの会社で15年という長きにわたって働いており、これまでさまざまなプロダクトやチームを経験して、いろいろな知識を身につけてきました。それらの知識を、これから一緒に働く仲間たちや担当するプロダクトに還元したいです。自分にしかできない、自分なりの貢献をしていけたら嬉しいですね。 

――チームやプロダクト、そしてユーザーに貢献するエンジニアは本当に素敵ですね。今回はありがとうございました。