前言
今天突然有一個需求是將文件的下載鏈接發(fā)送到給目標的手機短信宛逗,然后突然想起來自己接到的短信鏈接都是短鏈接帖池,然后就有了以下想法。Ps:都是想法慌申!想法陌选!網(wǎng)上的想法!
思路
如果沒有接觸過短網(wǎng)址理郑,不妨去 http://www.sina.lt/ 和 [https://dwz.cn/(https://dwz.cn/) 稍微體驗下或衡。體驗的結(jié)果是掉奄,短網(wǎng)址都把網(wǎng)址壓縮成了六個字符怎诫,這是巧合嗎惠险?
短網(wǎng)址整個運轉(zhuǎn)邏輯非常簡單,我們以 https://goo.gl/SfzlA2 為例抄腔,當我們訪問這個網(wǎng)址的時候蜀撑,后端可以獲取 "SfzlA2" 這個字符串村怪,然后跳轉(zhuǎn)到 https://github.com/hanzichi法瑟,很顯然冀膝,這個字符串和這個地址已經(jīng)綁定,通過某種映射關(guān)系可以從 "SfzlA2" 獲取完整的地址霎挟。
那么窝剖,看起來我們只需要找到一個算法,能夠?qū)⒁粋€長字符串壓縮成一個短的字符串酥夭,并且該算法應(yīng)該是可逆的赐纱。但是實現(xiàn)這樣的文本壓縮算法,是非常困難的(不存在熬北?)疙描,如果真有這么一個算法和逆運算,那么基本上現(xiàn)在的壓縮軟件都可以歇菜了蒜埋,而世界上所有的信息(網(wǎng)址長度未知)淫痰,都可以壓縮成固定長度個字符,這可能嗎整份?所以不要幻想使用壓縮算法,而且對于 URL 這種不超過 100 bytes 的字符串籽孙,壓縮算法的壓縮比通常都大于 1烈评。
所以我們應(yīng)該轉(zhuǎn)變思路。目前流行的短網(wǎng)址算法大概有兩種犯建,一種是利用 md5讲冠,將長網(wǎng)址 md5 后,再進行分組壓縮适瓦,因為 md5 實質(zhì)上是一種哈希算法竿开,所以難免出現(xiàn)碰撞,當然玻熙,我們有解決哈希沖突的 N 種方法否彩,但是這只會增加系統(tǒng)的復(fù)雜度,不推薦嗦随。另外一種是將網(wǎng)址和一個 62 進制數(shù)(0-9 & a-Z)對應(yīng)列荔,存入數(shù)據(jù)庫中,需要的時候,通過數(shù)據(jù)庫查詢提取贴浙。
上面都是我粘貼的砂吞,哈哈哈哈哈哈,我的想法就是通過一種縮短的算法崎溃,然后將映射關(guān)系放在數(shù)據(jù)庫啊或者緩存啊之類的蜻直,有一段生效時間,防止有重復(fù)之類的袁串,這個時候的縮短算法就很重要了袭蝗。
原理解析
當我們在瀏覽器里輸入 http://t.cn/ReCqY16 時
- DNS首先解析獲得 http://t.cn 的
IP
地址 - 當
DNS
獲得IP
地址以后(比如:119.75.217.109/),會向這個地址發(fā)送HTTP
GET
請求般婆,查詢短碼RlB2PdD
-
http://t.cn 服務(wù)器會通過短碼
ReCqY16
獲取對應(yīng)的長 URL - 請求通過
HTTP
301
轉(zhuǎn)到對應(yīng)的長 URL https://www.baidu.com/ 到腥。
這里有個小的知識點,為什么要用 301 跳轉(zhuǎn)而不是 302 吶蔚袍?
301 是永久重定向乡范,302 是臨時重定向。短地址一經(jīng)生成就不會變化啤咽,所以用 301 是符合
http
語義的晋辆。同時對服務(wù)器壓力也會有一定減少。
但是如果使用了301
宇整,我們就無法統(tǒng)計到短地址被點擊的次數(shù)了瓶佳。而這個點擊次數(shù)是一個非常有意思的大數(shù)據(jù)分析數(shù)據(jù)源。能夠分析出的東西非常非常多鳞青。所以選擇302雖然會增加服務(wù)器壓力霸饲,但是我想是一個更好的選擇。來自知乎 iammutex 的答案
算法實現(xiàn)
網(wǎng)上比較流行的算法有兩種 自增序列算法臂拓、 摘要算法
算法一
自增序列算法 也叫永不重復(fù)算法
設(shè)置 id 自增厚脉,一個 10進制 id 對應(yīng)一個 62進制的數(shù)值,1對1胶惰,也就不會出現(xiàn)重復(fù)的情況傻工。這個利用的就是低進制轉(zhuǎn)化為高進制時,字符數(shù)會減少的特性孵滞。
短址的長度一般設(shè)為 6 位中捆,而每一位是由 [a - z, A - Z, 0 - 9]
總共 62 個字母組成的,所以 6 位的話坊饶,總共會有 62^6 ~= 568億種組合泄伪,基本上夠用了。
哈哈幼东,這里附上一個進制轉(zhuǎn)換工具 http://tool.lu/hexconvert/ 上圖的數(shù)據(jù)就是用這個工具生成的臂容。
具體的算法實現(xiàn)科雳,自行谷歌。
算法二
- 將長網(wǎng)址
md5
生成 32 位簽名串,分為 4 段, 每段 8 個字節(jié) - 對這四段循環(huán)處理, 取 8 個字節(jié), 將他看成 16 進制串與 0x3fffffff(30位1) 與操作, 即超過 30 位的忽略處理
- 這 30 位分成 6 段, 每 5 位的數(shù)字作為字母表的索引取得特定字符, 依次進行獲得 6 位字符串
- 總的
md5
串可以獲得 4 個 6 位串,取里面的任意一個就可作為這個長 url 的短 url 地址
這種算法,雖然會生成4個,但是仍然存在重復(fù)幾率
其他
這樣的實現(xiàn)脓杉,還有一些其他的問題糟秘,比如短網(wǎng)址的長度并不是固定的,這點容易解決球散,補位即可尿赚。再比如,這些短網(wǎng)址蕉堰,按照順序排列凌净,并不顯得隨機,這也好辦屋讶,比如可以隨機生成六位字符串當作 key冰寻,而不是用整數(shù)的遞增,這樣的話皿渗,短網(wǎng)址數(shù)量也不受限了(可以增加短網(wǎng)址位數(shù))斩芭。還有一點,相同的 URL 可能得到不同的短網(wǎng)址乐疆,這點可以另外加個哈匣裕或者用 Set 去解決,還可以加個緩存來解決(在緩存時間內(nèi)挤土,重定向到相同地址琴庵,一旦緩存失效,重新分配 key)仰美。
除了算法設(shè)計外迷殿,真正的系統(tǒng)還需要考慮很多,比如發(fā)號器的設(shè)計筒占,比如緩存(掛個 Redis)贪庙,比如跳轉(zhuǎn),等等翰苫,本文只是我自己瞎想的,也沒實現(xiàn)这橙,都是一些想法奏窑。
短網(wǎng)址系統(tǒng)的設(shè)計,其實依賴的并不是文本壓縮算法屈扎。有些時候埃唯,需要換個角度思考問題。