設計一個系統將長鏈接地址轉為短鏈接地址


背景

最近遇到一個面試題,問請你設計一個系統將長鏈接轉為短鏈接。起初回答的不是很好,之后通過自己思考和查閱資料將這塊的內容進行整理。

研究

定義

短地址(也叫 短網址:Short URL)就是為了讓一個很長的網站鏈接縮短為一個短的鏈接,因為微博內有字數限制,所以短地址就是為了這個而產生的。大部分微博、手機短信提醒等地方已經有很多應用了。

優勢

  • 節省網址長度,便於社交化傳播。
  • 方便后台跟蹤點擊量、地域分布等用戶統計。
  • 規避關鍵詞、域名屏蔽手段。
  • 隱藏真實地址,適合做付費推廣鏈接。

總之

1、鏈接變短,在對內容長度有限制的平台發文,可編輯的文字就變多了

最典型的就是微博,限定了只能發 140 個字,如果一串長鏈直接懟上去如連接后面是100個“has11nut06bab2y3”這樣的字符的時候,其他可編輯的內容就所剩無幾了,用短鏈的話,鏈接長度大大減少,自然可編輯的文字多了不少。再比如一般短信發文有長度限度,如果用長鏈,一條短信很可能要拆分成兩三條發,本來一條一毛的短信費變成了兩三毛。另外用短鏈在內容排版上也更美觀。

2、我們經常需要將鏈接轉成二維碼的形式分享給他人,如果是長鏈的話二維碼密集難識別,短鏈就不存在這個問題了。

跳轉原理

我們可以認為他是整個交互的流程,具體的流程細節如下:

(1)用戶訪問短鏈接:https://dwz.date/fn4w

(2)短鏈接服務器dwz.date收到請求,根據URL路徑fn4w獲取到原始的長鏈接(KV緩存數據庫中去查找):https://www.cnblogs.com/lingyejun/p/15894620.html

(3)服務器返回302狀態碼,將響應頭中的Location設置為:https://www.cnblogs.com/lingyejun/p/15894620.html

(4)瀏覽器重新向https://www.cnblogs.com/lingyejun/p/15894620.html發送請求;

(5)返回響應;

具體方案

優化方案

算法優化

短鏈接標識一般是 [0-9, a-z, A-Z] 隨機組合而成的字符串,字符一共有 62 個,因此短鏈接標識可以用 62 進制的字符串表示。

首先維護一個自增的 ID,當生成短鏈接時,將 10 進制的自增 ID 轉換成 62 進制字符串,這個字符串就可以唯一標識一個長鏈接。由於 ID 是自增的,對應的 62 進制字符串是不同的,這樣就不會出現一個短鏈接對應多個長鏈接的問題,62 個字符排列組合,可以保證短鏈接是用不完的,就算僅限於 6 位長度標識的短鏈接,也有 558 億多種情況,這種算法在網上被稱為自增序列算法。

1、62 進制的順序並不一定嚴格按照 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 的順序來表示,這個順序可以是打亂的,這樣生成的短鏈接標識更隨機不易被破解。

2、長鏈接與短鏈接是否需要一對多關系,同一個長鏈接使用自增主鍵 ID 算法生成的短鏈接是不同的,因為自增主鍵 ID 不同,生成的 62 進制字符串自然也不同。如果我們有一個長鏈接唯一對應一個短鏈接需求,可以將長鏈接進行 md5 加密,將加密后的 md5 值存儲在 DB 中,每次生成短鏈接前都根據長鏈接 md5 值查詢 DB,如果存在,則直接返回短鏈接,當然也可以使用其他方式維護這種關系。

短地址發號器優化方案

1、算法優化

采用以上算法,如果不加判斷,那么即使對於同一個原始URL,每次生成的短鏈接也是不同的,這樣就會浪費存儲空間(因為需要存儲多個短鏈接到同一個URL的映射),如果能將相同的URL映射成同一個短鏈接,這樣就可以節省存儲空間了。主要的思路有如下兩個:

方案1:查表

每次生成短鏈接時,先在映射表中查找是否已有原始URL的映射關系,如果有,則直接返回結果。很明顯,這種方式效率很低。

方案2:使用LRU本地緩存,空間換時間

使用固定大小的LRU緩存,存儲最近N次的映射結果,這樣,如果某一個鏈接生成的非常頻繁,則可以在LRU緩存中找到結果直接返回,這是存儲空間和性能方面的折中。

2、可伸縮和高可用

如果將短鏈接生成服務單機部署,缺點一是性能不足,不足以承受海量的並發訪問,二是成為系統單點,如果這台機器宕機則整套服務不可 用,為了解決這個問題,可以將系統集群化,進行“分片”。

在以上描述的系統架構中,如果發號器用Redis實現,則Redis是系統的瓶頸與單點,因此,利用數據庫分片的設計思想,可部署多個發號器實例,每個實例負責特定號段的發號,比如部署10台Redis,每台分別負責號段尾號為0-9的發號,注意此時發號器的步長則應該設置為10(實例個數)。

另外,也可將長鏈接與短鏈接映射關系的存儲進行分片,由於沒有一個中心化的存儲位置,因此需要開發額外的服務,用於查找短鏈接對應的原始鏈接的存儲節點,這樣才能去正確的節點上找到映射關系。

參考文章:

https://blog.csdn.net/xlgen157387/article/details/80026452

https://blog.csdn.net/codejas/article/details/106102452

https://blog.csdn.net/coderising/article/details/105085655


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM