核心思路
- 長網址 → MD5 → 檢查 Memcached 是否已存在對應 ID
- 不存在則用 Memcached
increment() 產生自增 ID(起始 10000)
- 將 ID 轉為 62 進位(0-9, a-z, A-Z)短碼
- 雙向映射:
MD5 → ID、短碼 → 原網址 皆存入 Memcached
- 短網址格式:
https://xxx.com/短碼
完整類別實作
<?php
class Build_URL {
private $mem;
private $base_url = 'https://xxx.com/';
public function __construct() {
$mem_conf = [
['host' => '192.168.10.90', 'port' => 11116],
['host' => '192.168.10.90', 'port' => 11117],
];
$this->mem = new Memcache();
foreach ($mem_conf as $v) {
$this->mem->addServer($v['host'], $v['port']);
}
}
// 長網址 → 短網址
public function encode($url) {
$url = trim($url);
if (!preg_match('#^https?://|ftp://#i', $url)) return false;
$md5 = md5($url);
$aid = $this->mem->get($md5);
if (!$aid) {
if (($aid = $this->mem->increment('auto_increment_id')) === false) {
$this->mem->set('auto_increment_id', 10000);
$aid = $this->mem->increment('auto_increment_id');
}
$this->mem->set($md5, $aid);
$key = $this->dec2any($aid);
$this->mem->set($key, $url);
} else {
$key = $this->dec2any($aid);
}
return $this->base_url . $key;
}
// 短網址 → 長網址
public function decode($url) {
$key = str_replace($this->base_url, '', trim($url));
return $this->mem->get($key);
}
// 10 進位 → 62 進位
private function dec2any($num, $base = 62, $index = false) {
$out = '';
if (!$base) $base = strlen($index);
if (!$index) $index = substr('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 0, $base);
$t = ($num == 0) ? 0 : floor(log10($num) / log10($base));
for (; $t >= 0; $t--) {
$a = floor($num / pow($base, $t));
$out .= substr($index, $a, 1);
$num -= $a * pow($base, $t);
}
return $out;
}
}
// 測試
$app = new Build_URL();
$urls = ['https://www.baidu.com', 'https://www.google.com', 'https://www.jb51.net'];
foreach ($urls as $v) {
$short = $app->encode($v);
echo "Short: $short\n";
$orig = $app->decode($short);
echo "Original: $orig\n";
}
?>
關鍵細節補充
- Memcached 叢集:建構子支援多節點,自動分散讀寫
- ID 起始值 10000:避免短碼過短(如 1 字元)影響美觀與衝突率
- 62 進位編碼:62^n 組合,6 字元可達 568 億組合,足夠大多數場景
- 持久化問題:Memcached 重啟資料遺失,生產環境建議加 Redis 持久化或 MySQL 同步備份
- 並發安全:
increment() 為原子操作,天然支援高併發
擴充建議
- 加入自訂短碼功能(檢查唯一性)
- 統計點擊數、來源、地理位置
- 設定過期時間、存取密碼、單次有效等進階屬性
- 提供 API 介面(JSON 格式)供前端/行動端呼叫