〖雜七雜八〗-- 短URL連接系統

【短URL連接系統】

定義:  

  短網址(Short URL),顧名思義就是在形式上比較短的網址。但不知道有多少人像我同樣,因爲面試問道才知道有這種系統而對短鏈接原理好奇,從而進行進一步的研究。在Web 2.0的今天,不得不說,這是一個潮流。目前已經有許多相似服務(短網址服務,如今大部分微博、手機郵件提醒等地方已經有不少應用模式了,並佔據了必定的市場),藉助短網址您能夠用簡短的網址替代原來冗長的網址,讓使用者能夠更容易的分享連接。例如:http://t.cn/SzjPjA。mysql

  自從twitter推出短網址(shorturl),繼之國內各大微博跟風,google公開goo.gl使用API,短網址之風愈演愈烈。不得不說這是一個新興又一大熱門web2.0服務。web

爲何要這樣作的,緣由我想有這樣幾點:面試

  一、微博限制字數爲140字一條,那麼若是咱們須要發一些鏈接上去,可是這個鏈接很是的長,以致於將近要佔用咱們內容的一半篇幅,這確定是不能被容許的,因此短網址應運而生了。
  二、短網址能夠在咱們項目裏能夠很好的對開放級URL進行管理。有一部分網址能夠會涵蓋暴力,廣告等信息,這樣咱們能夠經過用戶的舉報,徹底管理這個鏈接將不出如今咱們的應用中,應爲一樣的URL經過加密算法以後,獲得的地址是同樣的。
  三、咱們能夠對一系列的網址進行流量,點擊等統計,挖掘出大多數用戶的關注點,這樣有利於咱們對項目的後續工做更好的做出決策。redis

短鏈接構成:

  協議+域名+參數算法

  例如:http://t.cn/SzjPjA 主要是參數:SzjPjA。這個是惟一標識。sql

短連接的好處:

  一、內容須要;數據庫

  二、用戶友好;瀏覽器

  三、便於管理。緩存

短鏈接用途:

  最簡單的用途就是他的名字直譯「短」的「連接」,能夠把長長的一串連接(例如:亞馬遜的購買連接)縮短成爲幾個簡單的字符。服務器

短鏈接原理:

  短鏈接原理很是簡單,就是用戶訪問短鏈接地址,到達咱們的短鏈接網站,而後網站經過短鏈接裏的code,查詢數據庫獲得原始url,而後讓網頁跳轉到原始url便可。

  一、針對小型應用:
    1)經過發號策略,給每個過來的長地址,發一個號便可,小型系統直接用mysql的自增索引就搞定了。
    2)建立一張數據庫表,僅須要有2列便可:code列和url列。code列也就是標識列,建議直接設置爲自增主鍵。用於存儲短鏈接參數代碼,也就是短鏈接裏的code。

  url列用於存儲要跳轉的原始url。

  二、針對大型應用:
    能夠考慮各類分佈式key-value系統作發號器。不停的自增就好了。第一個使用這個服務的人獲得的短地址是http://xx.xx/0 第二個是 http://xx.xx/1 第11個是 http://xx.xx/a

   依次日後,至關於實現了一個自增字段便可。

  所說的連接推廣分析功能,就是在這個過程當中,記錄訪客的某些信息,例如:訪問時間、訪問的短連接、訪客的IP、訪客的UserAgent信息等。基於這些信息,配合推廣方式,就能夠輔助判斷出什麼時間,什麼範圍,什麼人羣的推廣更有曝光效果。

短連接實現方法:

面試時,個人回答:
  一、小型的就用數據庫就好,利用自增ID做爲參數;
  二、大型的也就是高併發的狀況,使用redis這種k-v存儲系統進行存儲。個人思路以下:利用列表存儲,每一個列表存儲1萬個數據;redis中每一個列表的key從1開始(也就是對1萬作整除);若是想獲得某個短連接對應的原地址,那就經過divmod函數進行計算,他的商就表明是第幾個列表,餘數表明他的位置。這樣去獲取。
  三、若是使用redis去實現的化,怎麼保證你的系統內存不被撐爆?就是說我上一種存儲機制是徹底把數據存放在內存中的!我當時的回答是每隔一段時間作一次持久化。
  四、內存的問題解決了,可是若是過一段時間我再來獲取我存放的原url地址(假如我作持久化的時間是每隔12個小時,原數據已經存放到數據庫中),這種狀況怎麼解決?我當時的回答是從數據表(表結構的設計是:原url,還有個num列)中批量獲取一段數據,放入redis(可是這樣的話就沒有考慮高訪問的狀況,至關因而又把內存撐爆了)。

  五、併發的問題。

網上查找獲得的解決方案:(由簡入難)

第一種:
  26個大寫字母 26小寫字母,10個數字,隨機生成6個而後插入數據庫對應一個id,短鏈接跳轉的時候,根據字符串查詢到對應id,便可實現相應的跳轉!不過2的62次方,不知道有沒有重複的,小几率能夠,可是對應不是很大的網站應該足夠了。

第二種:
  經過發號策略進行存儲
幾個子問題:
一、如何用數據庫或者KV存儲來作? 
  用10進制去記錄。好比第10000個長地址,咱們給它的短地址對應的編號是9999,咱們經過存儲自增拿到9999後,做爲參數加到短連接以後;另外一種方式就是拿到這個數以後,再作一個進制轉換,例如10進制轉成16進制(晉級版的能夠考慮加密)。

二、如何實現同一個長地址屢次轉換,出來仍是同一個短地址?
  上面的發號原理中,是不判斷長地址是否已經轉過的。也就是說用拿着百度首頁地址來轉,我給一個http://xx.xx/abc 過一段時間你再來轉,我還會給你一個 http://xx.xx/xyz。這看起來挺很差的,可是很差在哪裏呢?很差在不是一一對應,而一長對多短。這與咱們完美主義的基因不符合,那麼除此之外還有什麼不對的地方? 
  有人說它浪費空間,這是對的。同一個長地址,產生多條短地址記錄,這明顯是浪費空間的。那麼咱們如何避免空間浪費,有人很是迅速的回答我,創建一個長對短的KV存儲便可。嗯,聽起來有理,可是。。。這個KV存儲自己就是浪費大量空間。因此咱們是在用空間換空間,並且貌似是在用大空間換小空間。真的划算嗎?這個問題要考慮一下。固然,也不是沒有辦法解決,咱們作不到真正的一一對應,那麼打個折扣是否是能夠搞定?
  這個方案最簡單的是創建一個長對短的hashtable,這樣至關於用空間來換空間,同時換取一個設計上的優雅(真正的一對一)。而實際狀況是有不少性價比高的打折方案能夠用。個人方案是:用key-value存儲,保存「最近」生成的長對短的一個對應關係。注意是「最近」,也就是說,我並不保存全量的長對短的關係,而只保存最近的。好比採用一小時過時的機制來實現LRU淘汰。

這樣的話,長轉短的流程變成這樣: 
  1.0 在這個「最近」表中查看一下,看長地址有沒有對應的短地址 
  1.1 有就直接返回,而且將這個key-value對的過時時間再延長成一小時 
  1.2 若是沒有,就經過發號器生成一個短地址,而且將這個「最近」表中,過時時間爲1小時
  因此當一個地址被頻繁使用,那麼它會一直在這個key-value表中,總能返回當初生成那個短地址,不會出現重複的問題。若是它使用並不頻繁,那麼長對短的key會過時,LRU機制自動就會淘汰掉它。
  固然,這不能保證100%的同一個長地址必定能轉出同一個短地址,好比你拿一個生僻的url,每間隔1小時來轉一次,你會獲得不一樣的短地址。這樣作對整個短系統是沒有影響的。

三、如何保證發號器的大併發高可用?
  上面設計看起來有一個單點,那就是發號器。若是作成分佈式的,那麼多節點要保持同步加1,多點同時寫入,這個嘛,以CAP理論看,是不可能真正作到的。其實這個問題的解決很是簡單,咱們能夠退一步考慮,咱們是否能夠實現兩個發號器,一個發單號,一個發雙號,這樣就變單點爲多點了?依次類推,咱們能夠實現1000個邏輯發號器,分別髮尾號爲0到999的號。每發一個號,每一個發號器加1000,而不是加1。這些發號器獨立工做,互不干擾便可。並且在實現上,也能夠先是邏輯的,真的壓力變大了,再拆分紅獨立的物理機器單元。1000個節點,估計對人類來講應該夠用了。若是你真的還想更多,理論上也是能夠的。

四、具體存儲如何選擇?
  這個問題就不展開說了,各有各道,主要考察的是對存儲的理解。對緩存原理的理解,和對市面上DB、Cache系統可用性,併發能力,一致性等方面的理解。

五、跳轉用301仍是302?  這也是一個有意思的話題。首先固然考察一個候選人對301和302的理解。瀏覽器緩存機制的理解。而後是考察他的業務經驗。301是永久重定向,302是臨時重定向。短地址一經生成就不會變化,因此用301是符合http語義的。同時對服務器壓力也會有必定減小。   可是若是使用了301,咱們就沒法統計到短地址被點擊的次數了。而這個點擊次數是一個很是有意思的大數據分析數據源。可以分析出的東西很是很是多。因此選擇302雖然會增長服務器壓力,可是我想是一個更好的選擇。

相關文章
相關標籤/搜索