高並行性: アゴダのシステムデザイン面接から学んだこと

# 高並行性: アゴダのシステムデザイン面接から学んだこと

シニアフルスタックエンジニアとしての面接を共有します。私の英語が十分でなく、面接官にとっては厳しい状況でした。

面接の部屋に足を踏み入れたとき、私はチャレンジに直面していることを理解しました。これは 2 回目の面接です。

Agoda でシニアフルスタックの職位に応募する旅に乗り出す中で、フロントエンドとバックエンドの両方の技術にわたる深さと広がりに重点を置いたこの役割は、面接プロセスが自然に複雑さとデザインの期待値を高めることを意味していることをよく理解していました。

この反省は、私のシニアフルスタック面接の没入体験に深く立ち入り、高度な技術的要求とアセスメントを形作る複雑なデザインの側面に洞察を提供します。このプロセスを通じて、私の技術力だけでなく、シニアレベルでの幅広い専門知識の重要性を強調しました。

しかし、大切なことは、私の英語が流暢ではなく、それが私にオファーを失わせました。次のステップは、技術スキルだけでなく、コミュニケーションスキルとソフトウェア能力を向上させることに焦点を当てることです。

## 面接プロセス

**タスク 1：** 単純なフロントエンドのタスクでした。React、useState、useEffect、およびデバウンスの基本的な知識が主に説明されました。私にとっては簡単だと思います。

**タスク 2：** 高並行性のシステムデザイン：ユーザー数を表示および保存する方法は？特に 100 万人のユーザーと 20 万人のユーザーが同時に製品詳細ページにアクセスする場合はどうですか？詳細ページで数を表示するためのフロントエンドとバックエンドの設計方法は？

この質問を受けると、このような高並行性を処理するシステムの設計は、様々な側面を慎重に考慮する多面的な試みであり、注意深く検討が必要であることを認識しました。

そのため、私は次のステップを 2 つの側面からこの問題を解決するために説明しました：

**1. フロントエンド：**

フロントエンドでは、ユーザーに製品詳細ページを現在表示している個人の数のリアルタイムの更新を提供することが重要です。これを実現するために、私は 2 つの戦略を提案しました：

- **CDN 静的リソース：** すべてのリソースを js、css、画像などを含む CDN に配置します。これによりサーバーへの負荷が軽減され、ユーザーエクスペリエンスが向上します。リソースのサイズを減少させたい場合は、画像を結合するためにスプライトを使用することもできます。ただし、これはウェブサイトの性能を向上させるための簡単な方法であり、重要なポイントではありません。

- **Websocket と SSE（Event-Source）：** http プロトコルを直接 ws プロトコルにアップグレードします。したがって、ws プロトコルまたは SSE 接続を実装してフロントエンドとバックエンドの間でリアルタイム通信を行います。これにより、ユーザーはユーザーカウントのリアルタイムの更新を受け取ることができます。

**2. バックエンド：**

バックエンドは、ユーザーカウントの処理とリアルタイムデータの効率的な提供の中核です。高並行性の課題に対処するために、私は以下の戦略を提案しました：

- **負荷分散と API ゲートウェイ：** 負荷分散器と API ゲートウェイを活用して、複数のサーバーとバックエンドインスタンスに入力トラフィックを分散させます。これにより、バックエンドは高いリクエストのボリュームを処理し、効率的に提供することができ、また単一のコンポーネントがボトルネックになるのを防ぎます。
  - API ゲートウェイに Rate-Limiting を設定することで、バックエンドが過剰なリクエストで圧倒されないようにできると思います。バックエンドを安定させるのに役立つと考えています。
- **マイクロサービスアーキテクチャ：**
  - **キャッシュメカニズム：** ユーザーカウントを格納するためのインメモリキャッシュメカニズムを統合します。Redis などを使用して、カウントデータを迅速かつ効率的に取得できます。これにより、データベースへの負荷が軽減され、応答時間が向上します。
  - **友達との話し合いの結果、Redis は永続性のメカニズムもサポートしています。Append-Only File（AOF）および Redis データベース（RDB）スナップショットなどです。サーバーの障害が発生した場合、ログファイルを読み取ることでデータを回復できます。**
  - **歴史的データのための DB：** ユーザーカウントの履歴データを格納するためにデータベースを直接使用します。これにより、ユーザーの行動傾向の分析と洞察が可能になります。
  - **Restful API + MQ：** Restful API とメッセージキュー（MQ）の組み合わせを使用してフロントリクエストを処理します。バックエンドサービスと効果的に対話し、更新のための非同期通信を確保します。このアプローチは高並行性と大量のリクエストの処理に適しており、リクエストの処理に対する拡張性と柔軟性も提供します。実際には、ユーザーカウントです。
  - **RPC ProtoBuf：** マイクロサービス間の通信に RPC ProtoBuf を使用します。ただし、面接期間中に正確な「ProtoBuf」の名前を忘れてしまい、最終的には「バイ

ナリバッファプロトコル」と表現しました。これは大きな誤りであると考えています。一時的なデータベースを設定して ProtoBuf データを格納し、フラグステータス変数を追加して消費の準備ができたかどうか、データがすでに消費されているかを示します。これにより、データの一貫性が向上し、データフローを効率的に管理します。**RPC の文脈でフラグを追加するこの方法は、通常、イベント駆動のアーキテクチャに適しています。非同期通信と柔軟性をサポートします。フラグの状態は、複数のアクションが同時に発生するシナリオに特に適しており、`ready for`、`consumption`、`processing`、`consumed`などの状態を示すことができます。**

## 見逃した点

まとめると、いくつかの重要な考慮事項を見落としていました。

1. データの一貫性と同時操作の正確性を確保する。これらの課題に対処するために、ロック、トランザクション、分離レベルなどのメカニズムを説明する必要があり、これらの課題に対処するための証拠をより強化する必要があります。
2. 負荷分散アルゴリズム、キャッシュ戦略、API デザイン、およびメッセージキューの選択に対する徹底した考慮。異なる負荷分散アルゴリズムの取り扱い、キャッシュの消去ポリシーの議論、RESTful API デザイン原則の詳細な説明、およびさまざまなメッセージキューオプションの比較は、システムデザインの複雑さに対するより包括的な理解を示すでしょう。
3. 高並行性における WebSocket 接続の管理とリソース管理。高並行性の期間中に WebSocket 接続を効果的に管理し、リソースの利用を処理する方法については詳しく説明していません。接続プーリング、スロットリング、リソースモニタリングなどのテクニックについて議論することで、実用的な課題の対処能力を強調することができます。

# 結論

最終的に、私は面接で十分なパフォーマンスを発揮できなかったと考えています。そのため、私は引き続き英語を話す能力を向上させる必要があります。また、システムデザインについてもっと学ぶ必要があります。問題解決能力を向上させるための良い方法だと思います。