短鏈接服務設計

設計 數據庫 算法 Redis onebite0 2019-05-28

之前遇到一道面試題,設計一個短網址服務設計,在這裡累述,希望能在你的碎片時間裡有個提醒。

一開始的想法,最好不經過存儲,算法可逆。你仔細一想,發現是異想天開,又要短又要可逆,沒那麼完美的事。

在這裡,先總結下短網址的優點:

1. 短連接在分享或者發送消息時減少字節佔用;

2. 在對url進行數據統計時,可以省去部分空間,如在redis統計pv等;

3. 隱藏必要的消息,避免一些有害攻擊,如釣魚攻擊;

實現短網址,逃不過存儲,將短網址和長網址Map起來。所以,它有兩個關鍵點,短碼和存儲。

數據庫自增ID轉base62

短碼生成,常見的有兩種方式,第一種自然是數據庫自增ID,加進制轉換,十進制轉其他進制以獲取用更少的位數產生更大的組合集。

如果用0-9,[A-Z],[a-z]共62個字符代表一位,而且絕對足夠你使用,試了下,9999999999999999才去到9位數(j2qDRMMYU)。

這個集合有多大?針對網上,有種計算是62^6個(6位),是有問題的。請注意,這是一個排列組合題,大家可以自己算算。

具體實現如下:

短鏈接服務設計

如果想防止其他人拿到你的ID,可以將字母順序隨機打亂。

哈希拆解

通過哈希實現,網絡上找到的,其意思是經過以下步驟,碰撞的概率會降低:

1. 將長網址md5成一個32位的字符串,分為4段,每段8個字節;

2. 依次將其中一段8個字節,轉成16進制,並與0x3fffffff進行與運算,目的去掉高兩位,保留30位二進制;

3. 將30位二進制拆成6段,每5位的十進制數作為字母表的索引取得特定字符,依次取得6位字符作為短碼;

4. 總共得到四個短碼,任取其一,碰撞概率得以除以4;

這裡的核心思想是增加選擇,降低碰撞,你也可以在第一步的時候,才採用幾種算法或者將url加上多個隨機序列或者將每段組合與運算下,多分出N段字節來。

其實,碰撞概率真的降低了嗎?一開始,我們會想,假設第一步兩個長鏈接hash碰撞了,經過一系列轉換後,我只取其中四份一,顯然碰撞降低了。

但另一方面,兩個長鏈接hash本身不碰撞的,現在去取四份一,碰撞的機率加大了。所以,我持反對意見,限於機器資源不夠,無法給出測試,簡單測試1000000個沒出現碰撞。

不過它做成一件事,32位縮成了6位,0和1的可能變成62個種可能。代碼實現如下:

短鏈接服務設計

短鏈接服務設計

問題回答到這裡,也許離面試官的標準答案還差一大截,就看你要面的是P幾。因為不可逆,需要要存儲和服務。

如此,所有短連接請求,憑空多一層轉碼,得儘量做到無感吧。

夜已深,文章再次爛尾,實在抱歉,可以在評論區討論。

相關推薦

推薦中...