111 lines
5.1 KiB
Markdown
111 lines
5.1 KiB
Markdown
|
||
## 本地端啟動(測試用)
|
||
|
||
[//]: # (請先設定資料庫)
|
||
|
||
```bash
|
||
go mod tidy
|
||
# 進入 etc/gateway.yml 設定各依賴的 config
|
||
go run url.go
|
||
```
|
||
|
||
### 本地啟動需要依賴套件或工具
|
||
|
||
以下已 macOS 為例,若已安裝或有其他可用服務則可跳過
|
||
|
||
- go-zero goctl (https://go-zero.dev/docs/tasks/installation/goctl)
|
||
```bash
|
||
$ go install github.com/zeromicro/go-zero/tools/goctl@latest
|
||
```
|
||
- protobuf (https://protobuf.dev/)
|
||
```bash
|
||
brew install protobuf
|
||
```
|
||
|
||
## Docker 啟動 (Production)
|
||
|
||
```bash
|
||
make build-docker
|
||
make run-docker
|
||
```
|
||
|
||
## 目錄結構
|
||
```aiignore
|
||
├── Makefile # 用於構建和運行專案的自動化腳本
|
||
├── etc
|
||
│ └── url.yaml # 服務配置檔,例如端口號、資料庫連線等
|
||
├── generate # 產生服務的目錄
|
||
│ └── api
|
||
│ └── url_generate.api # API 定義檔,描述服務介面和資料結構
|
||
├── go.mod
|
||
├── go.sum
|
||
├── internal # 內部模組目錄,不對外暴露
|
||
│ ├── config
|
||
│ │ └── config.go # 配置管理邏輯,負責加載和解析配置檔
|
||
│ ├── handler
|
||
│ │ ├── routes.go # 路由註冊檔案,將請求分發到對應的處理器
|
||
│ │ └── url
|
||
│ │ └── # URL 相關請求處理器目錄,具體實現短網址的創建、查詢等功能
|
||
│ ├── logic
|
||
│ │ └── url
|
||
│ │ └── # 核心業務邏輯層,實現短網址生成、存儲和讀取
|
||
│ ├── module
|
||
│ │ └── url
|
||
│ │ └── # URL 子模組的實現,封裝功能細節
|
||
│ ├── svc
|
||
│ │ └── service_context.go # 服務上下文,管理全域依賴(如資料庫連線等)
|
||
│ └── types
|
||
│ └── types.go # 通用型別定義,例如請求和回應的結構體
|
||
├── readme.md # 專案說明檔,描述專案目標、使用方法等
|
||
├── url.go # 服務的入口檔案,負責啟動服務
|
||
└── url.json # 服務元數據或範例配置檔,用於輔助開發或測試
|
||
```
|
||
|
||
## 設計思路
|
||
|
||
IDAllocator 是一個基於 Bitmap的簡單 ID 分配器,用於管理有限數量的 ID。通過位圖來標記 ID 的使用狀態,每個位對應一個唯一的 ID,從而高效地分配和釋放資源。
|
||
|
||
### 核心設計理念
|
||
1. 使用 math/big 提供的 big.Int 作為位圖,記錄每個 ID 是否已被分配。
|
||
2. 同步安全:通過 sync.Mutex 確保分配和釋放操作的線程安全性。
|
||
3. 編碼與解碼:將位圖中的索引轉換為 URL 友好的短碼(使用 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_ 作為字符集),以便對外提供友好的短字符串表示。
|
||
|
||
### 功能說明
|
||
#### 分配 ID (Allocate)
|
||
* 從位圖中找到第一個未使用的位置,分配對應的 ID。
|
||
* 將該位設為 1 表示已分配,並返回經過編碼的短字符串。
|
||
|
||
#### 釋放 ID (Release)
|
||
* 將傳入的 ID 解碼為位圖索引。
|
||
* 將對應位設為 0,表示該 ID 已釋放,可重複使用。
|
||
|
||
#### ID 編碼 (encodeIndex)
|
||
* 將位圖索引轉換為固定長度(5 字符)的短碼。 -> **故目前可用會是64 的五次方個(考慮單機架構),已夠用,如果需要分散式可以再討論**
|
||
* 確保生成的 ID 短小且唯一。
|
||
|
||
#### ID 解碼 (decodeIndex)
|
||
* 將短碼還原為位圖索引,確保釋放或其他操作可以正確定位。
|
||
|
||
|
||
### 限制與考量
|
||
1. 前可用會是 64 的五次方個(考慮單機架構),已夠用,如果需要分散式可以再討論
|
||
2. 目前設計並沒有考慮壞掉重啟,只有讓他不斷插入,在資料庫設定為一所以,插入不了就會在產新的,的消極處理方案
|
||
如果需求需要重啟復原,可以在討論如何做
|
||
|
||
|
||
|
||
### 分布式設計考量
|
||
|
||
#### 如果需要支持分布式環境,需引入全局一致性和協作管理,可能的改進方向包括:
|
||
|
||
1. 集中式位圖管理:
|
||
* 使用集中式存儲(例如 Redis 或 Zookeeper)存儲位圖數據。
|
||
* 各實例在分配和釋放時,通過原子操作更新集中位圖。
|
||
2. 分段分配:
|
||
* 將 ID 空間劃分為多段,分配給不同的節點,每個節點管理自己的位圖。
|
||
* 節點之間通過協議(如 Raft)協作管理段的分配。
|
||
3. 雪花算法(Snowflake Algorithm):
|
||
* 基於時間戳、機器 ID 和序列號生成全局唯一的 ID。
|
||
* 適用於大規模分布式系統。
|
||
|
||
時間尚短,測試先只做最基本的short_code_utils |