如何設計短網址系統?
短網址的長度
短網址的長度該設計為多少呢? 當前網際網路上的網頁總數大概是 45億,超過了 232=42949672962^{32}=4294967296232=4294967296,那麼用一個64位整數足夠了。
一個64位整數如何轉化為字串呢?,假設我們只是用大小寫字母加數字,那麼可以看做是62進位制數,log62(264−1)=10.7log_{62} {(2^{64}-1)}=10.7log62(264−1)=10.7,即字串最長11就足夠了。
實際生產中,還可以再短一點,比如新浪微博採用的長度就是7,因為 627=352161460620862^7=3521614606208627=3521614606208,這個量級遠遠超過網際網路上的URL總數了,絕對夠用了。
現代的web伺服器(例如Apache, Nginx)大部分都區分URL裡的大小寫了,所以用大小寫字母來區分不同的URL是沒問題的。
因此,正確答案:長度不超過7的字串,由大小寫字母加數字共62個字母組成
一個長網址,對應一個短網址,還是可以對應多個短網址? 這也是個重大選擇問題
一般而言,一個長網址,在不同的地點,不同的使用者等情況下,生成的短網址應該不一樣,這樣,在後端資料庫中,可以更好的進行資料分析。如果一個長網址與一個短網址一一對應,那麼在資料庫中,僅有一行資料,無法區分不同的來源,就無法做資料分析了。
以這個7位長度的短網址作為唯一ID,這個ID下可以掛各種資訊,比如生成該網址的使用者名稱,所在網站,HTTP頭部的 User Agent等資訊,收集了這些資訊,才有可能在後面做大資料分析,挖掘資料的價值。短網址服務商的一大盈利來源就是這些資料。
正確答案:一對多
現在我們設定了短網址是一個長度為7的字串,如何計算得到這個短網址呢?
最容易想到的辦法是雜湊,先hash得到一個64位整數,將它轉化為62進位制整,擷取低7位即可。但是雜湊演算法會有衝突,如何處理衝突呢,又是一個麻煩。這個方法只是轉移了矛盾,沒有解決矛盾,拋棄。
MySQL資料庫有一個自增ID,能不能借鑑這個呢?每來一個長網址,就給它發一個號碼,這個號碼不斷的自增。這個方法跟雜湊相比,好處是沒有衝突,不用考慮處理衝突的問題。如何實現單臺的發號伺服器呢?可以用一臺MySQL伺服器來做(一定要用 REPLACE INTO
,不要儲存所有ID),也可用一臺Redis伺服器(用INCR
),一行程式碼也不用寫;也可以自己寫一個RESTful API,程式碼也很簡單,就不贅述了。
單臺發號器有什麼缺點呢?它是一個單點故障(SPOF, Single Point Of Failure),也會成為效能瓶頸(其實,如果你的QPS能大到壓垮這臺MySQL,那說明你的短網址服務很成功,可以考慮上市了:D),所以它適合中小型企業,對於超大型企業(以及在面試顯得追求高大上),我們還是要繼續思考更好的方案,請接著往下看。
下面開始講如何打造多臺機器組成的分散式發號器。
-
使用[UUID]演算法或者MongoDB產生的[ObjectID]。其實MongoDB的ObjectID也算是一種UUID,這類演算法,每臺機器可以獨立工作,天然是分散式的,但是這類演算法產生的ID通常都很長,那短網址服務還有什麼意義呢?所以這個方法不行。
-
多臺MySQL伺服器。前面講了單臺MySQL作為發號伺服器,那麼自然可以擴充套件一下,比如用8臺MySQL伺服器協同工作,第一臺MySQL初始值是1,每次自增8,第二臺MySQL初始值是2,每次自增8,一次類推。前面用一個 round-robin load balancer 擋著,每來一個長網址請求,由 round-robin balancer 隨機地將請求發給10臺MySQL中的任意一個,然後返回一個ID。[Flickr用的就是這個方案],僅僅使用了兩臺MySQL伺服器。這個方法僅有的一個缺點是,ID是連續的,容易被爬蟲抓資料,爬蟲基本不用寫程式碼,順著ID一個一個發請求就是了,太方便了(手動斜眼)。
-
分散式ID生成器(Distributed Id Generator)。分散式的產生唯一的ID,比如 Twitter 有個成熟的開源專案,就是專門做這個的,[Twitter Snowflake] 。Snowflake的核心演算法如下:
最高位不用,最高位不用,永遠為0,其餘三組bit佔位均可浮動,看具體的業務需求而定。預設情況下41bit的時間戳可以支援該演算法使用到2082年,10bit的工作機器id可以支援1023臺機器,序列號支援1毫秒產生4095個自增序列id。
[Instagram用了類似的方案],41位表示時間戳,13位表示shard Id(一個shard Id對應一臺PostgreSQL機器),最低10位表示自增ID,怎麼樣,跟Snowflake的設計非常類似吧。這個方案用一個PostgreSQL叢集代替了Twitter Snowflake 叢集,優點是利用了現成的PostgreSQL,容易懂,維護方便。
因此,正確答案:分散式發號器(Distributed ID Generator),Flick, Twitter Snowflake 和 Instagram的方案都是不錯的選擇。
如果儲存短網址和長網址的對應關係?以短網址為 primary key, 長網址為value, 可以用傳統的關聯式資料庫存起來,例如MySQL, PostgreSQL,也可以用任意一個分散式KV資料庫,例如Redis, LevelDB。
如果你手癢想要手工設計這個儲存,那就是另一個話題了,你需要完整地造一個KV儲存引擎輪子。當前流行的KV儲存引擎有LevelDB何RockDB,去讀它們的原始碼吧。
這也是一個有意思的問題。這個問題主要是考察你對301和302的理解,以及瀏覽器快取機制的理解。
301是永久重定向,302是臨時重定向。短地址一經生成就不會變化,所以用301是符合http語義的。但是如果用了301, Google,百度等搜尋引擎,搜尋的時候會直接展示真實地址,那我們就無法統計到短地址被點選的次數了,也無法收集使用者的Cookie, User Agent 等資訊,這些資訊可以用來做很多有意思的大資料分析,也是短網址服務商的主要盈利來源。
所以,正確答案是302重定向。
可以抓包看看新浪微博的短網址是怎麼做的,使用 Chrome 瀏覽器,訪問這個URL [],是我事先發微博自動生成的短網址。來抓包看看返回的結果是啥,
可見新浪微博用的就是302臨時重定向。
如果一些別有用心的駭客,短時間內向TinyURL伺服器傳送大量的請求,會迅速耗光ID,怎麼辦呢?
首先,限制IP的單日請求總數,超過閾值則直接拒絕服務。
光限制IP的請求數還不夠,因為駭客一般手裡有上百萬臺肉雞的,IP地址大大的有,所以光限制IP作用不大。
可以用一臺Redis作為快取伺服器,儲存的不是 ID->長網址,而是 長網址->ID,僅儲存一天以內的資料,用LRU機制進行淘汰。這樣,如果駭客大量發同一個長網址過來,直接從快取伺服器裡返回短網址即可,他就無法耗光我們的ID了。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2325/viewspace-2797000/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- URL短網址系統的演算法設計及實踐演算法
- W外鏈 短網址系統API 原始碼,網址縮短API介面API原始碼
- url.cn短網址 url.cn短網址網址縮短教程
- 如何縮短淘寶客連結網址 淘客短網址線上生成教程
- 微信短網址 微信短網址(url.cn)線上生成介面
- 騰訊短網址(url.cn短網址) 2020最新騰訊短網址生成api介面推薦API
- url.cn短網址 騰訊url.cn短網址生成介面
- http://t.cn短網址 新浪t.cn短網址是如何申請開通的HTTP
- 各種系統參考設計網址 比如ERP
- win10系統設定中遮蔽某個網址怎麼操作 win10系統如何設定遮蔽某個網址Win10
- 短網址安全淺談
- Google短網址的APIGoAPI
- 微信url短網址線上生成 最新微信短網址生成平臺推薦
- T.CN短網址 新浪T.CN短網址生成工具推薦
- 騰訊短網址(url.cn)新浪短網址(t.cn)的API介面分享API
- W外鏈短網址生成,他們家的短網址免費的嗎?
- URL短網址線上生成工具
- 微信短網址線上生成 推薦幾個可在線上生成微信短網址的平臺
- 網址多語言設計
- 系統設計:如何設計Youtube?
- 系統設計實踐(01) - 短鏈服務
- 短連結系統的設計與實現
- 短網址生成API介面,短鏈生成 W外鏈API介面API
- 京東短網址高可用提升最佳實踐
- 短連結URL系統是怎麼設計的?
- 2024年好用的短連結短網址工具推薦
- 大型網際網路系統架構是如何設計的?架構
- 大型企業網路系統整合方案如何設計?
- 新浪短網址(t.cn/xxx)介面 最新新浪t.cn短網址線上生成平臺推薦
- [譯] 原子設計:如何設計元件系統元件
- 作業系統下載網址彙總作業系統
- 一個固定資產系統方面的網址。
- mongodb短網址專案02具體實現MongoDB
- [JAVA VC] 短網址生成,HTTP請求,隨想JavaHTTP
- Win10系統輸入網址卻開啟其他網站如何解決Win10網站
- 如何利用新浪官方的短網址API介面實現T.cn短連結的壓縮生成API
- 最新最穩定的騰訊短網址(URL短連結)API介面分享API
- 如何設計一個微博系統?- 4招教你搞定系統設計