Skip to content

Zhima-Mochi/linkZapURL

Repository files navigation

linkZapURL - System Design for URL Shortener Service

Table of Contents

Introduction

linkZapURL is a URL shortening service. It is a simple service that takes a long URL and returns a short URL. When a user visits the short URL, it will redirect to the long URL.

Features

  • Horizontal scalability (sharding, unique ID generator)
  • Snowflake ID (timestamp + machineID + sequence) as unique ID
  • Cache (including non-exist codes' requests)
  • base58 encoding

Architecture

High Level Design

High Level Design

MongoDB Schema Design for URL Collection

Each document in the url collection represents a tiny URL entity, structured as follows:

{
  "ID": int64,          // Unique ID generated by Snowflake algorithm
  "shardID": int64,     // Derived from `ID`, used for sharding
  "url": string,        // Actual URL
  "expireAt": int64     // Expiration timestamp
}

Unique index: (shardID, ID).

Redis key-value Design for Cache

Redis is used to cache the tiny URL entity. The key is the encoded ID of the entity, and the value is the JSON string of the entity (URL and expiration timestamp).

Base58 Encoding Functions

Encode(num int64) string

  • Converts a 64-bit integer to a base58 encoded string.
  • Ensures output is up to 7 characters long.

Decode(code string) int64

  • Converts a base58 encoded string (7 characters) back to a 64-bit integer.

Final Architecture

All of the services are deployed in local machine for demonstration purpose. In production, the services should be deployed in different physical or virtual machines.

Final Design

API Sequence Diagram

Shortening Service

Shortening Service Sequence Diagram

Redirection Service

Redirection Service Sequence Diagram

Tech Stack

Run

My environment: WSL2

# Start MongoDB
cd ./docker/mongodb && ./init.sh && cd ../..
# Start Redis
cd ./docker/redis && ./init.sh && cd ../..
# Start Nginx
cd ./docker/nginx && ./init.sh && cd ../..
# Start Service
./init.sh
# Host: http://localhost

Configurations

See config.yaml.

Endpoints

  • GET /swagger/index.html

linkZapURL Service

  • POST /api/v1/shorten

    Request Body:

    {
        "url": "<original_url>",
        "expireAt": "<expired_time>" // format: RFC3339
    }

    Response Body:

    {
        "id": "<code>",
        "shortUrl": "http://localhost/<code>"
    }
  • GET /:code

    Redirect to the original URL