长链接转短链接的一次尝试
偶然的一次業務需求,需要使用到這樣的功能。雖然很多大平臺提供了這樣的接口(新浪,百度等等)。但是還是對其中的原理想在梳理一下。
我們不妨先來看一下短鏈接服務的整個流程,以前面提到的微博短網址服務為例。用戶輸入想要縮短的長網址,轉化后得到一個以http://t.cn開頭的短網址,然后用戶將該鏈接通過微信或者微博等方式分享給朋友,其他人點擊之后即可進入原本長網址所對應的頁面。整個流程如下圖所示:
? ? ? ? ? ? ? ? ? ? ? ?
從圖中可以很清楚地看到,實現短鏈接服務的關鍵是兩個步驟:1、如何把一個任意長的字符串轉化成一個較短的字符串;2、從短網址如何還原出長網址。第一個問題很容易讓人想到哈希算法,通過一定的方式將任意長的文本轉化成一個固定長度的字符串,只要目標字符串的長度適當,那么不同的輸入幾乎不可能對應同一個字符串。不過這么做有個缺點就是無法從得到的結果還原輸入的字符串,因此不適用于我們的場景。但基于哈希算法的思想,我們可以設計一種以多進制為基礎的算法完成這個任務。
具體而言,我們可以創建一個用于保存長網址的數據表,比如就叫Url,這張表很簡單,只需要兩個字段,一個主鍵用于保存id,一個url字段用于存放原始的長網址,每個長網址都在這張表有一條記錄。當進行長網址轉換時,先檢查數據表中是否存在該長網址,若是直接獲取該記錄的id,否則在數據表中創建一條新記錄,并返回其id。對于這個id,我們可以得到一個多進制表示下的新值,比如在以“0-9a-z”這36個字符表示的36進制中,一億這個數字可以被表示成1njchs,只需要6個字符即可,將這6個字符拼接到準備好的域名后即可得到一個對應的短網址返回給用戶。由于一億個網址只需要6個字符,因此這種方式足夠滿足大部分網站的需求。
而當用戶點擊了我們生成的短網址后,只需要將代表多進制的這部分提取出來,還原成十進制的數字后查表即可得到原始的長網址,再根據網址做一個重定向即可讓用戶訪問到原始的網頁。具體的實現可以參考下面的typescript代碼
這里的config.shortLinkBaseUrl也就是我們用來做短鏈接服務的域名,在前面的例子中就是http://t.cn,我們需要在這個域名對應的服務器內實現短鏈接的服務,同時這個域名本身不能太長,否則就失去了它的意義。另外還有一點值得注意,就是在根據長網址去數據表查找它是否存在時,因為長網址可以任意長,因此直接用它作為索引在數據表中查找的話效率較低,可以考慮在表中增加一個hash字段,保存長網址的哈希值,并通過查找哈希值來判斷條目是否存在,提高查找的效率。
以上就是短鏈接服務的基本實現方法,最核心的其實就是多進制的使用。
當然網上還有一種對于這種功能實現最優的方法。
最優的算法
通過發號原理
顧名思義這個系統的第一個請求過來了,我們以微博為例,短鏈接系統的第一個請求我們可以給變為t.cn/0,第二個t.cn/1等等;
實現的方式也會很簡單
1、小型的系統用MySQL的自增索引就可以滿足。
2、大型系統可以考慮分布式key-value系統。
存儲原理
發號策略是這樣的,當一個新的鏈接過來時,發號器發一個號與之對應。往后只要有新鏈接過來,發號器不停發號就好。舉個例子,第一個進來的鏈接發號器發0號,對應的短鏈接為 xx.xxx/0,第二個進來的鏈接發號器發1號,對應的短鏈接為 xx.xxx/1,以此類推。
發號器發出的10進制號需要轉換成62進制,這樣可以大大縮短號碼轉換成字符串后的長度。比如發號器發出 10,000,000,000 這個號碼,如果不轉換成62進制,直接拼接在域名后面,得到這樣一個鏈接 xx.xxx/10000000000。將上面的號碼轉換成62進制,結果為AOYKUa,長度只有6位,拼接得到的鏈接為 xx.xxx/AOYKUa。可以看得出,進制轉換后得到的短鏈接長度變短了一些。6位62進制數,對應的號碼空間為626,約等于568億,所以基本上不用擔心發號器無號可發的情況。
高并發場景下
上面設計看起來有一個單點,那就是發號器。如果做成分布式的,那么多節點要保持同步加1,多點同時寫入。這樣難以避免產生單點性能瓶頸。因此我們可以考慮將單點變為多點。我們可以引入多個機器,我們可以設定機器A發號只發向100取余等于0的數字100n,同理機器B只發向100取余等于1數字 100n+1,以此類推,各個機器相互獨立互不干擾,我們可以隨時擴展我們的機器了。
同一長鏈接,每次轉成的短鏈接是否一樣
同一長鏈接,每次轉成的短鏈接不一定一樣,原因在于如果查詢緩存時,如果未命中,發號器會發新號給這個鏈接。需要說明的是,緩存應該緩存經常轉換的熱門鏈接,假設設定緩存過期時間為一小時,如果某個鏈接很活躍的話,緩存查詢命中后,緩存會刷新這個鏈接的存活時間,重新計時,這個鏈接就會長久存在緩存中。
我們也可以引入LRU算法。進行淘汰我們不經常使用到的鏈接。
重定向問題
選取301,還是302?
301是永久重定向,302是臨時重定向。
如果選擇301:短地址生成以后就不會變化,所以用301是符合http語義的。同時對服務器壓力也會有一定減少。這樣一來,我們就無法統計到短地址被點擊的次數了。
如果選擇302:選擇302雖然會增加服務器壓力,但是可以統計到短地址被點擊的次數了,我可以針對點擊的次數來進行后期的大數據處理,機器學習,以及推薦算法。
選擇302還是301,想必讀者心中有肯定有數了。
以上就是我看到網上的一下帖子。特此放在一起。也算做個參考吧。雖然是一個很小的需求,但是還是有的深究的。
總結
以上是生活随笔為你收集整理的长链接转短链接的一次尝试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Mac共享主机网络给虚拟机
- 下一篇: SAP BP最佳业务实践