设计短链接服务
问题
如何用 Rust 设计一个短链接生成和重定向服务?
答案
架构设计
核心实现
use axum::{Router, routing::{get, post}, extract::{State, Path}, Json, response::Redirect};
use std::collections::HashMap;
use std::sync::{Arc, atomic::{AtomicU64, Ordering}};
use tokio::sync::RwLock;
struct ShortUrlService {
counter: AtomicU64,
url_map: RwLock<HashMap<String, String>>, // short_code → original_url
}
const BASE62: &[u8] = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
impl ShortUrlService {
fn new() -> Self {
Self {
counter: AtomicU64::new(100_000), // 从较大的数开始,保证短码长度
url_map: RwLock::new(HashMap::new()),
}
}
/// 自增 ID → Base62 编码
fn encode_base62(mut num: u64) -> String {
if num == 0 { return "0".to_string(); }
let mut result = Vec::new();
while num > 0 {
result.push(BASE62[(num % 62) as usize]);
num /= 62;
}
result.reverse();
String::from_utf8(result).unwrap()
}
async fn shorten(&self, url: &str) -> String {
let id = self.counter.fetch_add(1, Ordering::Relaxed);
let short_code = Self::encode_base62(id);
self.url_map.write().await.insert(short_code.clone(), url.to_string());
short_code
}
async fn resolve(&self, code: &str) -> Option<String> {
self.url_map.read().await.get(code).cloned()
}
}
// API 路由
async fn create_short_url(
State(svc): State<Arc<ShortUrlService>>,
Json(req): Json<CreateRequest>,
) -> Json<CreateResponse> {
let code = svc.shorten(&req.url).await;
Json(CreateResponse {
short_url: format!("https://short.url/{}", code),
})
}
async fn redirect(
State(svc): State<Arc<ShortUrlService>>,
Path(code): Path<String>,
) -> Result<Redirect, axum::http::StatusCode> {
match svc.resolve(&code).await {
Some(url) => Ok(Redirect::temporary(&url)),
None => Err(axum::http::StatusCode::NOT_FOUND),
}
}
短码生成策略对比
| 策略 | 冲突率 | 长度可控 | 可预测 |
|---|---|---|---|
| 自增 ID + Base62 | 无冲突 | ✅ | 是(可猜测) |
| MD5/SHA 截取 | 可能冲突 | ✅ | 否 |
| 随机生成 | 可能冲突 | ✅ | 否 |
| 雪花算法 + Base62 | 无冲突 | 较长 | 否 |
常见面试问题
Q1: 如何避免短码被猜测?
答案:
自增 ID 的短码是连续的,可以被遍历。解决方案:
- ID 混淆:对自增 ID 做可逆的位运算混淆
- 随机 ID:用
uuid生成随机 ID 再 Base62 编码 - 加盐哈希:
hash(url + salt)取前 N 位
生产环境通常用方案 1(ID 混淆),兼顾无冲突和不可预测。