この記事は 食べログアドベントカレンダー2022 の24日目の記事です🎅🎄
はじめに
こんにちは、食べログ予約サービスチームの菅原です。バックエンドを担当しています。
今回は食べログアドベントカレンダー2022の16日目の記事で紹介した「食べログのネット予約システムとは」から、より技術的な部分にフォーカスを当てた記事となっています。
まだ記事を読んでいない方はこの機会にぜひ読んでいただけると幸いです!
ネット予約システムとは
店舗が簡単にネット予約を受け付けられ、予約情報を管理できるシステムのことです。
食べログでの予約方法はいくつかあります。
- 即予約(みなさんが目にするネット予約のことです)
- リクエスト予約
- 電話予約
この中でネット予約システムを使っているのは「即予約」と「リクエスト予約」です。
このネット予約システムを導入している店舗であれば、ユーザはWebサイトやアプリから簡単に予約登録が可能です。
●ユーザ側の予約登録画面
●店舗側の管理画面(食べログノート)
ネット予約システムの構成図
ネット予約システムではユーザが利用する画面と店舗が利用する画面の主に2種類を管理しています。
食べログ 予約
ユーザ向けの予約登録画面です。PC版やスマートフォン版、アプリ版を提供しています。 みなさんアプリから利用する部分です!
食べログノート
店舗会員向けの予約管理システムです。2022年4月にリリースされ現在では多くの店舗で導入されているものです。
フロントエンドではReact + Next.js + TypeScriptで作られており、クエリ言語としてGraphQLが存在し、 バックエンドはRuby + Ruby on Railsで作成されているシステムとなっています。
ネット経由、電話経由、ウォークスルーのすべてのパターンを一元管理できるシステムとなっており、PC版とアプリ版を提供しています。
予約サーバ
食べログの予約にまつわる登録・更新・キャンセルなどのAPIを取り扱うサーバです。 多くの予約が見込まれるケースに応じてスケーリングし常に高負荷にならないように運用を行っています。
店舗管理サーバ
店舗会員向けのメニューを提供しているサーバです。食べログノートをはじめ、コース設定やレストラン情報、契約情報などを管理しています。
バッチサーバ
バッチサーバでは数十、数百件に及ぶ月次、週次、日次バッチが稼働しています。 在庫計算をはじめとする高パフォーマンスが必要な箇所はApache Kafkaを利用し分散処理を実施しています。
また、バッチ単体だけではなく複数扱う場合は専用のジョブ管理システムを利用しています。
技術スタック
開発環境
- 開発PC: MacBook Pro
- ソース管理:Git
- 開発エディタ: 自由(VSCode(code-server)、Vim)
フロントエンド
- Language: TypeScript
- Framework: React + Next.js
- Library: jQuery ※ 古いソースで利用中。絶賛移行しています。
- Query Language: GraphQL
バックエンド
- Language: Ruby
- Framework: Ruby on Rails
- DB: MySQL
- Web Server: nginx
- Application Server: Unicorn
- 非同期処理:Redis + Resque
- 分散キューイングシステム:Apache Kafka + Sidekiq
ピックアップ技術
在庫計算・在庫サマリ
在庫とは、予約の空き状況を指します。
在庫サマリとは、前もって在庫状況を計算しておくことで、予約可能な日時、人数の情報をユーザに提供する仕組みです。 この仕組みを使うことで、ユーザが目にするカレンダーの◯、△、✕が表示され、いつネット予約可能かを瞬時に検索、確認できます。
在庫サマリは初期開発時にいくつか問題点があり、その改善に関して簡単にピックアップしたいと思います。
改善前の在庫計算処理方法
- シーケンシャルに処理
- 数百件単位のトランザクションで計算
- エラー検知時はターミナルからの手動キュー投入
改善前の状況でも正常運用はできていましたがいくつかの問題点がありました。
問題点
- シーケンシャルのため1店舗でも遅い処理があると待ち状態が発生する
- 1店舗の処理時間が長いせいで、タイムアウトを検知してしまう
これらの状態の場合、後続の店舗は在庫サマリの計算がされないため、ユーザが目にするカレンダーの予約可能状況が 正しく表示されない状態となります。ただし、予約登録時に再度リアルタイムで在庫計算はしているため予約自体は可能です。
しかしながら、これではユーザが目にするカレンダーの予約可能状況と実際の予約可否があべこべな状況となり、ユーザ体験が悪い状態となってしまうので、早期改善が必要と判断しました。
まずはじめの改善策として、1店舗の処理が遅い場合は、内部処理を高速化するパフォーマンス改善を実施しました。 主な改善策は構造の見直しやN+1問題の解消、データのキャッシュ化です。
これらの問題はパフォーマンス改善だけでは解決することができない領域だったのでSREのような専門チームに相談する形となりました。 そして相談した結果、分散キューイングシステムのApache Kafkaを利用することで並列での処理を可能とするシステム構造に決めた形となります。
このApache Kafka自体は他のサブシステムでも実績があったので導入するまでのコストが低いことや一緒に利用しようと考えていたSidekiqとの相性もよかったので採用しました。 ただしこの並列化を可能とする方法を検討していくなかでいくつかの問題点が浮き彫りになりました。
インフラ面の導入は可能だが、アプリケーション面での人員が不足していた
よくあることだと思いますが多くのプロジェクトが並行して動いている状況で人員が不足しており、専任の人を当てることができない状況に陥っていました。 一般的だと現在のプロジェクトを止めてこちらの作業を優先することや、期間を先送りするなどが考えられると思われます。 ただ今回行った施策は、他の部やチームが連携したタスクフォースチームを発足することで対応するものでした。 私自身あまり聞かない方法での解決だったので驚きましたが、そのかいあって、優秀な人員が集まり作業を開始することができました。
在庫サマリが複雑で容易に機能改修ができなかった
在庫サマリはすべての在庫状況を計算し保存しておく必要があります。 日付の場合は3ヶ月先、時間で言えばほぼ24時間、人数で言えば1人から99人までの全パターンをすべて前もって計算することで、素早く予約カレンダーから在庫状況を確認できるようにしています。 扱うパターンや上記以外にも多くの条件があり複雑な状態となっています。
ただここに関しては一つ一つ丁寧に見ていくことしかできない部分だったので地道にやっていくことになりました。
キューの失敗した場合などの新しい運用課題が出た
キューを失敗した場合に手動で対応するのは運用コストが高かったので、ある一定回数分再実行する仕組みの検討をしました。 失敗したキューをテーブルに保存して、次回実行時にテーブルからキューに再び送られることでキューのロストを防ぐ形となります。
これ以外にも改善前ではターミナルから手動キュー投入を行っていましたが、Sidekiqを使うことでWebUIからの操作が可能となったので運用が大幅に楽になりました。
最終的に以下の在庫計算処理の形となりました。
現在では在庫計算バッチからApache Kafkaにメッセージが送られ並列でキューを処理し、Sidekiqで在庫計算を行っています。 失敗したキューに関しては再度Apache Kafkaを通して再実行されます。 問題点として挙げていた、「シーケンシャルのため1店舗でも遅い処理があると待ち状態が発生する」に関してはこの分散処理を構築することで解決しました。 もう一つの問題点であった「1店舗の処理時間が長いせいで、タイムアウトを検知してしまう」に関しては分散処理ではなく別の対応方法で改善しています。
そのことについては別の機会で記事にしていく予定です。 今回最終的にApache KafkaやSidekiqを利用していますが、食べログではそれらの技術要素に関して記事を書いていますので合わせてご確認ください。
- Debezium Usecases in Tabelog
- 食べログのレストラン検索を支える Debezium と Apache Kafka - Qiita
- 食べログの内製Pub/Subメッセージング基盤をApache Kafkaにリプレイスした話 - Qiita
データ量の取り扱い
在庫情報や店舗側で管理している予約データ、スケジュールデータなど大量のデータを取り扱っています。 店舗毎の席に対する日付データの洗替でauto incrementがMySQLのint桁数(2147483647≒21億)を超えたデータ保持が見受けられました。 このデータは洗替をしているため常に21億レコードを持っているわけではないですが、数年でこのauto_incrementに達するぐらいのレコード数を持ちます。 食べログのネット予約システムは大きなサービスとなり扱うデータも多いので日々監視やチューニングなどを行い運用しています。
最後に
お読みいただきありがとうございます! 食べログのネット予約を支える技術要素に関して興味を持って頂けたら幸いです。
食べログのバックエンドに興味がある仲間を募集しています。 気になった方はぜひチェックしてみてください。
明日はアドベントカレンダーラストを飾る、@tkyowaの「食べログにおける質の高いアウトプットを持続的に生み出す組織づくり」です。お楽しみに!