【ITニュース解説】Design TinyURL
2025年09月15日に「Dev.to」が公開したITニュース「Design TinyURL」について初心者にもわかりやすく解説しています。
ITニュース概要
URL短縮サービスは、長いURLを短いエイリアスに変換し、アクセス時に元のURLへリダイレクトする。主な機能は短縮・リダイレクト・分析で、高可用性・低遅延・耐久性が重要だ。設計では、短いコードと元のURLをDBに保存し、アクセス時に検索・リダイレクトを行う。NoSQLやキャッシュで高速化し、ランダム文字列ID生成やシャーディング等で大規模トラフィックに対応する。
ITニュース解説
あなたが普段インターネットを使っていると、とても長いウェブサイトのアドレス、つまりURLを見かけることがあるだろう。しかし、時にはその長いURLがたった数文字の短いURLに置き換えられていることに気づくかもしれない。これは「URL短縮サービス」というものが提供している機能だ。TinyURLやBitlyといったサービスがその代表例だが、これらは長いURLを受け取り、より短く覚えやすいエイリアス(別名)を生成し、その短いURLにアクセスしたユーザーを元の長いURLへ自動的に転送する役割を担っている。
このURL短縮サービスを構築する際には、いくつかの重要な要件を考慮する必要がある。まず機能面では、単に長いURLを短くするだけでなく、生成された短いURLから元の長いURLへ正確にリダイレクトする機能が必須となる。さらに、どの短いURLがどれくらいクリックされたかといった利用状況を分析する機能も求められることがある。
次に、このサービスがどれくらいの規模で利用されるかを想定することも重要だ。例えば、毎日1億人ものユーザーが利用し、そのうち毎日100万件もの新しい短いURLが作られると仮定する。さらに、短いURLが作られる(書き込み)回数に対して、その短いURLがクリックされる(読み込み)回数は100倍も多いと見積もられる。これは、このサービスが「読み込みが非常に多い」という特性を持つことを示している。作成されたデータは5年間保持する必要があり、一件あたりのデータサイズは500バイト程度と想定される。
これらの機能的な側面に加えて、サービスが安定して動くための非機能要件も非常に重要だ。例えば、「高可用性」とは、システムが24時間365日ほとんど停止することなく利用できる状態を指す。また、「低遅延」とは、短いURLをクリックした際に、元のURLへ速やかに(例えば200ミリ秒以内)リダイレクトされることを意味する。「高耐久性」は、たとえサーバーに何か問題が起こったとしても、データが失われることなく安全に保存され続けることを保証するものだ。
このようなサービスを実際に作る場合、どのように長いURLを短くし、また短いURLから元のURLへ戻すかを操作するための「APIエンドポイント」と呼ばれる入り口を用意する。URLを短縮したいときは、長いURLを含んだ情報を特定のAPI (POST /api/urls/shorten) に送ると、サービスから短いURLが返ってくる。そして、生成された短いURLをクリックした際は、別のAPI (GET /:shorturl) が呼び出され、そこから元の長いURLが取得されてユーザーのブラウザに転送されることになる。
システムの大まかな流れは次のようになる。まず、ユーザーが長いURLを短縮したいとリクエストを送ると、そのリクエストは「API Gateway」という、システムの入り口となる部分に到達する。API Gatewayは、そのリクエストを「URL短縮サービス」という処理を担当する部分に送る。URL短縮サービスは、受け取った長いURLに対応するユニークな「短いコード」を生成し、その短いコードと元の長いURLのペアをデータベースに保存する。最後に、生成された短いURLをユーザーに返す。
次に、誰かがその短いURLをクリックした場合、再びリクエストはAPI Gatewayを通って今度は「URLリダイレクトサービス」に送られる。リダイレクトサービスは、受け取った短いコードを使ってデータベースから対応する元の長いURLを探し出す。元のURLが見つかると、リダイレクトサービスはブラウザに対して「このURLに移動してください」という指示(HTTP 302または301リダイレクト)を出し、ブラウザはその指示に従って元の長いURLのウェブページを表示する。
ここで使われる「HTTP 302 Found」というリダイレクトは一時的な移動を意味するもので、ブラウザに対してこのリダイレクト情報を永続的に記憶しないように指示する。もし「HTTP 301 Moved Permanently」を使ってしまうと、ブラウザや検索エンジンはそのリダイレクトを永続的にキャッシュしてしまい、もし後で短いURLの指す先を変更したい場合に問題が生じる可能性があるため、一時的な302が適していることが多い。
データベースの選定も重要なポイントだ。URL短縮サービスでは、短いコードと長いURLの単純なペアを大量に保存し、高速に検索できれば十分であり、複雑なデータ間の関連付け(結合)はあまり必要ない。このような場合、「NoSQLデータベース」が非常に適している。NoSQLデータベースは、大量のデータに対する高速な読み書き処理、データの形式(スキーマ)の柔軟性、そして必要に応じてサーバーを追加して処理能力を増やす「水平スケーラビリティ」に優れているため、大規模なURL短縮サービスにはうってつけだ。例えば、DynamoDBやCassandraといった高可用性のNoSQLデータベースが候補になる。データベースには、短いコード、元の長いURL、作成日時、そして誰が作成したかを示すユーザーIDなどを保存するとよいだろう。
このサービスは「読み込みが多い」という特性があるため、システムを高速化するための工夫が必要だ。一つは「キャッシング層」の導入だ。Redisのような高速なメモリデータベースを利用し、頻繁にアクセスされる短いコードと長いURLのペアを一時的に記憶しておく。これにより、データベースへのアクセス回数を減らし、リダイレクトの遅延を大幅に短縮できる。キャッシュされたデータは、有効期限を設定したり、最も古いものから削除していくといったルールで管理される。もう一つは、データベースに「インデックス」を設定することだ。短いコードのフィールドにインデックスを付けることで、データベースが目的の長いURLを非常に速く見つけられるようになる。
短いURLの「短いコード」を生成する方法もいくつか考えられる。最も簡単なのは、サービス内で一意な番号を自動で増やしていくカウンターを使い、その番号を数字とアルファベットを組み合わせた「Base62」という形式に変換する方法だ。これはシンプルで短いコードが作れるが、一元的なカウンターが必要なため、システムを大きくするときのボトルネックになりやすい。 別の方法として、完全にランダムな短い文字列を生成し、それが既にデータベースに存在しないかを確認する方法がある。もし同じコードが見つかれば、別のランダムなコードを再生成する。この方法は、システムを分散させやすく、生成されるコードも予測しにくいのでプライバシーの面でも有利だが、ごくまれに衝突が発生する可能性は残る。 元の長いURL自体をMD5やSHAといったハッシュ関数で処理し、そのハッシュ値の先頭部分を短いコードとして利用する方法もある。同じ長いURLからは常に同じ短いコードが生成されるが、異なる長いURLから同じ短いコードができてしまう「衝突」のリスクがある。 あるいは、UUID(Universally Unique Identifier)と呼ばれる、世界中でほぼ重複しない識別子を生成し、それをエンコードして利用する方法もある。これは高いユニーク性を保証するが、生成されるコードが比較的長くなる傾向がある。多くの場合、ランダムな文字列を生成して衝突をチェックする方法が、スケーラビリティとコードの短さのバランスが良いため採用されることが多い。
最後に、大量のアクセス(高トラフィック)をさばくためのスケーリング戦略についても考える必要がある。「シャーディング」という手法では、データベースを複数の小さな部分に分割し、それぞれを異なるサーバーに保存することで、データの量と処理の負荷を分散させる。これにより、必要に応じてサーバーを追加していき、システム全体の処理能力を増やせる。 また、「ロードバランシング」は、ユーザーからのリクエストを複数のサーバーに均等に振り分けることで、特定のサーバーに負荷が集中しすぎてダウンするのを防ぐ役割を果たす。 さらに、CDN(コンテンツデリバリーネットワーク)のエッジキャッシングを利用することも有効だ。CDNは、世界中に分散配置されたサーバー(エッジロケーション)にデータをキャッシュする仕組みで、ユーザーは自分に最も近いエッジロケーションからデータを受け取れるため、リダイレクトの遅延が少なくなる。また、CDNがリクエストの一部を処理してくれるため、サービスのバックエンドサーバーへの負荷も軽減できる。
これらの様々な技術や設計の工夫を組み合わせることで、私たちは高機能で安定し、高速に動作するURL短縮サービスを構築できるのだ。