https://github.com/zhima-mochi/linkzapurl
System design for URL shortener service.
https://github.com/zhima-mochi/linkzapurl
docker docker-compose golang mongodb-sharding nginx redis-cluster system-design
Last synced: 4 months ago
JSON representation
System design for URL shortener service.
- Host: GitHub
- URL: https://github.com/zhima-mochi/linkzapurl
- Owner: Zhima-Mochi
- Created: 2024-01-19T10:37:07.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-01-26T13:26:45.000Z (over 2 years ago)
- Last Synced: 2025-06-18T08:51:47.119Z (about 1 year ago)
- Topics: docker, docker-compose, golang, mongodb-sharding, nginx, redis-cluster, system-design
- Language: Go
- Homepage:
- Size: 659 KB
- Stars: 3
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# linkZapURL - System Design for URL Shortener Service
## Table of Contents
- [Introduction](#introduction)
- [Features](#features)
- [Architecture](#architecture)
- [High Level Design](#high-level-design)
- [Final Architecture](#final-architecture)
- [API Sequence Diagram](#api-sequence-diagram)
- [Shortening Service](#shortening-service)
- [Redirection Service](#redirection-service)
- [Tech Stack](#tech-stack)
- [Run](#run)
- [Endpoints](#endpoints)
- [Swagger](#swagger)
- [linkZapURL Service](#linkzapurl-service)
## 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

### MongoDB Schema Design for URL Collection
Each document in the `url` collection represents a tiny URL entity, structured as follows:
```bash
{
"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.

## API Sequence Diagram
### Shortening Service

### Redirection Service

## Tech Stack
- [MongoDB](https://www.mongodb.com/): database, shard
- [Redis](https://redis.io/): cache, cluster
- [Docker](https://www.docker.com/): container
- [Docker Compose](https://docs.docker.com/compose/): container orchestration
- [gin](https://github.com/gin-gonic/gin)
- [nginx](https://www.nginx.com/): reverse proxy
## Run
My environment: WSL2
```bash
# 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](./docker/config.yaml).
## Endpoints
### [Swagger](./docs/swagger.json)
- `GET /swagger/index.html`
### linkZapURL Service
- `POST /api/v1/shorten`
Request Body:
```bash
{
"url": "",
"expireAt": "" // format: RFC3339
}
```
Response Body:
```bash
{
"id": "",
"shortUrl": "http://localhost/"
}
```
- `GET /:code`
Redirect to the original URL