[マイベストTech Lead rince氏]あらゆる商品を扱う商品データベースを再設計した話 #データ負債解消2

Connpass詳細はこちら

アーカイブはこちら

資料はこちら

今回は、弊社のサービスの事例を通してデータベースのアーキテクチャの再設計の進め方やあらゆる商品を扱う商品データベースの仕組みを中心に紹介していきます。

ユーザーの選択をサポートするmybest

まずは弊社が提供しているサービスの「mybest」について紹介します。

mybestはユーザーの選択をサポートする商品比較サービスで、月間利用者数は3000万人以上です。商品を自社で購入して、専門性を持ったメンバーが徹底検証を行って商品のランキングを作っています。

上段の真ん中の写真ではプールを貸し切って実際に潜って撮影して防水カメラの検証をしたり、その下の写真はチェーンソーの検証で、片道2時間ほどかけて山奥にこもってチェーンソーの検証をしたりして、ランキングを本気で作っています。

mybestのデータの特徴としては、先ほど申し上げたように自社で商品を購入して、スペックやレーティングなどの自社検証した唯一無二のデータを持っているところです。

また、あらゆるジャンルのあらゆる商品のサービスを扱っているため、カテゴリは5800、カテゴリに対して紐づいている商品のデータ数は約200万件あります。 あらゆるジャンルなので、スペックやレーティングのカラムを一律に定義できません。

例えば、洗濯機であれば大きさや洗濯容量や消費電力といったようにスペック情報やレーティングはカテゴリによって異なるのでカラムが事前に定義できません。

また、記事ページのランキングの中でスペックによる絞り込みやレーティングによる並び替えが可能になっています。掃除機であれば集じん方式やヘッドの種類などで絞り込めます。

サービスの成長に伴って商品DBの設計が負債に

少し前の話になりますが、社内メンバーから「管理画面のカテゴリページの表示に40秒以上かかる」といった声が挙がったり、POから「ランキングでスペック情報の並び替えや絞り込みをしたい」という要望が出たり、ユーザーから「このサイトはたまに重い」と言われる事象がありました。

先ほど話した自社検証の導入から数年経って、従来の設計では難しい部分が出てきたんですね。

当初の要件とは別の使い方をしたことによるデータの重複・大量増加、レコード数の増加やクエリの複雑化によるパフォーマンスの低下、ランキングの絞り込みや並び替えでより柔軟な検索を実現したいという要望が挙げられました。

実際サービスの成長を見ると、2018年の中頃から自社検証を開始してここ数年でデータも増えて、ユーザー数も大きく成長しています。

その中でリリース時は負債ではなかったものの、サービスの成長に伴って負債が出てきました。例えば、データ量・トラフィック・機能が増えたり、使われ方が変わったりして徐々に環境変化が起こり、技術的負債になったという形です。

mkitaharaさんの技術的負債の発生と返し方の判断基準の図を引用すると、技術的負債はリリース時に認知していたものとしてないものに分かれます。

認知していない負債も、そもそも負債だと思っていなかったケースと環境変化により技術的負債になったケースがあります。今回は環境変化による技術的負債が出てきた形です。

そこで、このままだとユーザーに継続して価値を届け続けられないので、現状の課題や要望に合わせて商品データベースの設計を見直すことになりました。

関係者へのヒアリングを基に商品DBを再設計

今回は「Design It」と「ソフトウェアアーキテクチャの基礎」という書籍を参考に商品データベースの再設計を進めました。

①課題抽出、②要件定義、③技術調査・設計、④開発とデータ移行という流れで、具体例を出しながら説明していきます。

まず①課題抽出です。ここではステークホルダーを整理しました。

以下の図はかなり簡略化していますが、POからは機能要望が来たり、いくつかの開発チームが日々機能追加を行っていたり、ユーザーさんがサービスを利用していたりと、関係者が多岐にわたっていました。

その後各ステークホルダーに現場の課題やニーズを30~60分ヒアリングして、さらにコンテキストを掘り下げて整理していきました。

全ての問題を解決するのは難しいので、ユーザー・ビジネス・技術においてサービス上ボトルネックとなる場所はどこで、解決可能なのかという観点で課題を選定しました。

その結果、範囲による絞り込みなど柔軟な商品検索の実現と重いページのパフォーマンス向上を解決していくことになりました。

続いて要件定義です。

要件定義ではアーキテクチャ上重要な要求(ASR)を明らかにすることが大事です。技術的な制約、ビジネス上の制約、影響力のある機能要求、 品質作成の要求を主にステークホルダーにヒアリングで明らかにしていきました。

特に今回は品質特性についての一例を説明します。

キャッシュが切れても1秒以内にレスポンスを返したい、adminで40秒かかっているページを数秒以内に返したいといったパフォーマンスの要求、検索の仕組みが応答しない場合でも数十秒以内に復旧できてほしいといった可用性の要求、商品数が今のペースで3年増えても耐えられるようにしたいスケーラビリティの要求がありました。

続いて、インセプションデッキとPRDを作成しました。

再設計には一定のリソースが必要なので、関係者の理解と協力が必須です。また、関係者へのメリットを提示して、期待値を調整することが大事です。

スライドの右下のインセプションデッキの例のように関係者で共通認識を取り、機能要求も継続的に関係者にヒアリングしながらPRDを詰めていきました。

続いて、技術調査と設計です。

ここでは課題を解決するための実現方法について各種技術をMUSTとWANTの要件で調査しました。今回のケースでは、MUSTは検索性・パフォーマンスや動的なフィールド追加、スケーラビリティでした。WANTはファセット検索と各フィールドでの切り替えです。

そして、ElasticsearchやAlgolia、 MySQL(Aurora)、DynamoDB(NoSQL)に関して技術調査をして、MUSTとWANTの要件を満たせるか、開発・運用コストも含めて評価しましたね。満たしている・満たしていない・一部満たしているという3段階で表を埋めていきました。

以上を踏まえて設計やアーキテクチャを決定していきます。特にMUSTの要件を満たすものの中で、さらに詳細にPros/Consを比較して決定しました。

今の状況に必要十分な設計・アーキテクチャを選ぶのが重要で、今回はElasticsearchとAlgoliaが共にMUST要件を満たしました。さらに、WANT要件や今後の拡張性も考えてElasticsearchを選択しました。

設計方針としてはボトルネックとなるテーブル構造を見直すことと、Elasticsearchを導入して絞り込みや並び替えを任せるといったことを決めました。

決定後は設計の内容をDesign Docにまとめました。プロジェクトの背景・目的・設計・検討した代替案など各設計ドキュメントを関係者と共有・議論することで、事前に全体を考察して精度を高めて、開発後の手戻りを防ぐ役割を担っています。

特に個人的には検討した代替案が重要だと思っています。ADR(Architecture Decision Record)を書く会社もありますが、他の選択肢やこの設計方式を選んだ理由をコンテキストとともに記録しておくことが非常に大事です。

今回の設計ではスペック情報の「管理用の値」を扱うテーブルが2000万レコードあってボトルネックになっていたり、既存の「検索タグ」の仕組みだと範囲検索ができない問題がありました。

なので、テーブル構造を見直して管理用の値をなくして、検索はElasticsearchに任せる形で、パフォーマンスの向上と柔軟な絞り込みを実現しました。

最後は開発データ移行です。

開発はリスクの高い部分から取り掛かるのが大事です。今回はElasticsearchのフィールドの動的な追加やフィールド数が増えた場合のパフォーマンス検証に先に取り掛かりました。

実際の実装では、フィードバックを設計に反映することも大事です。100%完璧な設計は最初からできないので、実装しながらフィードバックで反映していくのが良いと思っています。

今回だとElasticsearchのインデックスの持ち方やテーブル設計の見直しの微修正が入りました。

データ移行の部分では、サービスを止めずに既存データを安全に新形式に移行することを目指しました。並行稼働するためにテーブルに新形式かどうかのフラグを持たせて、フラグがONなら新形式としました。

このような形で新旧両方のテーブルに書き込みを行って、サービスを止めずにデータ移行を行いました。

また、影響の少ないカテゴリから実施してフラグをOFFにすれば切り戻せる形で、なるべく安全に新形式に移行できるようにしました。

あとは本番と同じ内容のデータのレビュー環境でまず移行を試して、担当者に使ってもらって問題無いことを確認しました。

商品DBの再設計によってパフォーマンスが大幅に改善

商品DB再設計の結果として範囲検索などの柔軟な絞り込みが可能になり、2000万レコードの巨大なテーブルを削除できました。

そして、編集画面のレスポンスタイムが40秒から1.6秒と96パーセント削減できました。 また、Admin全体のレイテンシも0.8秒から0.4秒と2倍改善して、劇的な成果を上げられました。

今回の経験から、最適な設計・アーキテクチャを選択するには、技術だけではなくビジネスやユーザーも合わせて幅広い視野で考える必要があるということを学びました。

頭の中には答えはないので、ステークホルダーにヒアリングして課題や要求を明らかにしていくフェーズが自分の中ではかなり大変で大切だったと感じました。

2つ目の学びは、ソフトウェアアーキテクチャはトレードオフであるということです。

アーキテクチャは絶対的な正解があるわけではなく、全て場合によります。トレードオフを分析した上で、複数の選択肢の中から自分たちの状況に最適なものを選ぶ必要があります。そして、状況が変われば正解も変わってきます。

今見えてないものを見通すことは難しいですが、今見えてるものを把握して、その中で必要十分な設計・アーキテクチャを選ぶことが大事です。ただ「見通すことが難しい=考えない」わけではなく、今見えてるものに対する把握を怠ってはいけません。

視聴者からの質問に答える質問タイムへ

――ここからは視聴者の方からの質問に回答していきます。まず一つ目は「環境変化によるデータ負債を早期に発見するための取り組みは何か行っているのでしょうか」とのことですが、いかがでしょうか。

Datadogを入れて対応しています。Datadogを使ってパフォーマンスが悪化した時は通知が来るように設定したり、隔週でやっているエンジニアの相談会でアラートが上がったものに関してディスカッションしたり、 あとは月1で技術的負債を解消する日に簡単に解消できるものに対してパフォーマンス改善をしたりしています。

――続いて、「必要十分な設計アーキテクチャは、今回だと具体的にどのような状態だったのでしょうか」とのことですが、いかがでしょうか。

基本的にはMUSTの部分をまずは満たしているか、その後でWANTの可能性ですね。ただ、WANTの中でも優劣があります。

例えば、半年後にこの機能を実装したいというのが明白にわかっているケースと、1年以内にもしかしたらやるかもしれないというケースがあるんですね。その中で優劣をつけながら、より可能性の高いものは将来まで考えるようにバランスを取りながら最後は判断しました。

――続いて、「アーキテクチャのレビューはDesign Docsを用いてどのようなプロセスがあったのでしょうか」とのことですが、いかがでしょうか。

Design Docsを書いたらまずエンジニア内で全員がレビューできるようにしています。決まった場所にドキュメントを置いて、誰でも見れるような状態になっています。

その中で各テックリードは必須でレビューを行います。他のエンジニアは任意参加で、設計のレビューを実施した上で質問があれば答えてブラッシュアップしていく流れです。

この記事をシェア

関連記事


副業・フリーランス

プログラミング

デザイン

インタビュー

お金

採用・組織

転職

イベントレポート