這也是一道leetcode的題目html
leetcode-cn.com/problems/en…數據庫
生成短連接.後端
若是僅僅是作題,那麼其實有不少辦法.瀏覽器
在實際中,應該使用分佈式發號器(Distributed ID Generator)緩存
64位的整數能表示的範圍184467440737億遠遠大於全球網頁數量45億。來一個長網址,就分配一個ID去生成短網址.服務器
並且這樣能夠支持一個長網址對應多個短網址。通常而言,一個長網址,在不一樣的地點,不一樣的用戶等狀況下,生成的短網址應該不同,這樣,在後端數據庫中,能夠更好的進行數據分析。app
爲了方便轉化爲字符串,通常使用62進制,字符串的一位能夠是大小寫字母加數字共62個字母.分佈式
通常採用一個7位的字符串,62^7=3521614606208627=35216億.性能
其餘的辦法大概還有取HASH值的前N位,碰撞,不重複就爲短網址.這樣性能不高。
public class EncodeAndDecodeTinyURL {
Map<String, String> map = new HashMap<>();
long index = 10000; // 這裏是模擬一個當前計數值.
private static String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
private static int scale = 62;
// Encodes a URL to a shortened URL.
public String encode(String longUrl) {
String tinyUrl = indexToStr(index, 7);
map.put(tinyUrl, longUrl);
return tinyUrl;
}
public String indexToStr(long num, int length) {
StringBuilder sb = new StringBuilder();
int remainder = 0;
while (num > scale - 1) {
/** * 對 scale 進行求餘,而後將餘數追加至 sb 中,因爲是從末位開始追加的,所以最後須要反轉(reverse)字符串 */
remainder = Long.valueOf(num % scale).intValue();
sb.append(chars.charAt(remainder));
num = num / scale;
}
sb.append(chars.charAt(Long.valueOf(num).intValue()));
String value = sb.reverse().toString();
while (value.length() < length) {
value = "0" + value;
}
return value;
}
// Decodes a shortened URL to its original URL.
public String decode(String shortUrl) {
return map.get(shortUrl);
}
public static void main(String[] args) {
EncodeAndDecodeTinyURL codec = new EncodeAndDecodeTinyURL();
codec.decode(codec.encode("https://leetcode.com/problems/design-tinyurl"));
}
複製代碼
如下內容出自武林的回答
若是存儲短網址和長網址的對應關係?以短網址爲 primary key, 長網址爲value, 能夠用傳統的關係數據庫存起來,例如MySQL,PostgreSQL,也能夠用任意一個分佈式KV數據庫,例如Redis, LevelDB。 若是你手癢想要手工設計這個存儲,那就是另外一個話題了,你須要完整地造一個KV存儲引擎輪子。當前流行的KV存儲引擎有LevelDB何RockDB,去讀它們的源碼。
這也是一個有意思的問題。這個問題主要是考察你對301和302的理解,以及瀏覽器緩存機制的理解。 301是永久重定向,302是臨時重定向。短地址一經生成就不會變化,因此用301是符合http語義的。可是若是用了301, Google,百度等搜索引擎,搜索的時候會直接展現真實地址,那咱們就沒法統計到短地址被點擊的次數了,也沒法收集用戶的Cookie, User Agent 等信息,這些信息能夠用來作不少有意思的大數據分析,也是短網址服務商的主要盈利來源。因此,正確答案是302重定向。
若是一些別有用心的黑客,短期內向TinyURL服務器發送大量的請求,會迅速耗光ID,怎麼辦呢?
首先,限制IP的單日請求總數,超過閾值則直接拒絕服務。光限制IP的請求數還不夠,由於黑客通常手裏有上百萬臺肉雞的,IP地址大大的有,因此光限制IP做用不大。
能夠用一臺Redis做爲緩存服務器,存儲的不是 ID->長網址,而是 長網址->ID,僅存儲一天之內的數據,用LRU機制進行淘汰。這樣,若是黑客大量發同一個長網址過來,直接從緩存服務器裏返回短網址便可,他就沒法耗光咱們的ID了。