如脈脈,不會(huì)縱容你發(fā)太長(zhǎng)的網(wǎng)址,會(huì)給你轉(zhuǎn)成短鏈。
1.Scenario 場(chǎng)景根據(jù)一個(gè) long url 生成一個(gè)short url。
【資料圖】
如 http://www.javaedge.com => http://bit.ly/1ULoQB6
根據(jù) short url 還原 long url,并跳轉(zhuǎn):
需和面試官確認(rèn)的問題:
long url和short url必須一一對(duì)應(yīng)嗎?
Short url長(zhǎng)時(shí)間沒人用,需要釋放嗎?
1.1 QPS 分析問日活,如微博100M推算產(chǎn)生一條 tiny url 的 qps假設(shè)每個(gè)用戶平均每天 0.1(發(fā)10 條,有一條有鏈接) 條帶 URL 的微博
平均寫 QPS = 100M * 0.1 / 86400 = 100
峰值寫 qps = 100 * 2 = 200
推算點(diǎn)擊一條tiny url的 qps假設(shè)每個(gè)用戶平均點(diǎn) 1 個(gè)tiny url
平均寫 QPS = 100M * 1 / 86400 = 1k
峰值讀 qps = 1k * 2 = 2k
deduce 每天產(chǎn)生的新 URL 所占存儲(chǔ)100M * 0.1 = 10M 條
每條 URL 長(zhǎng)度平均按 100 算,共 1G
1T 硬盤能用 3 年
由2、3 分析可知,并不需要分布式或者 sharding,支持 2k QPS,一臺(tái) SSD MySQL 即可。
2.Service 服務(wù) - 邏輯塊聚類與接口設(shè)計(jì)該系統(tǒng)其實(shí)很簡(jiǎn)單,只需要有一個(gè) service即可:URL Service。由于 tiny url只有一個(gè) UrlService:
本身其實(shí)就是個(gè)小的獨(dú)立應(yīng)用也無(wú)需關(guān)心其他任何業(yè)務(wù)功能方法設(shè)計(jì):
UrlService.encode(long_url):編碼方法
UrlService.decode(long_url):解碼方法
訪問端口設(shè)計(jì),當(dāng)前有如下兩種常用主流風(fēng)格:
GET /REST 風(fēng)格Return a http redirect resonseREST 風(fēng)格Return a http redirect resonsePOST /data/shorten(不太推薦,不符合 REST 設(shè)計(jì)風(fēng)格,但也有人在用) returh a short url那么,你們公司的短鏈系統(tǒng)是選擇哪種服務(wù)設(shè)計(jì)呢?
3.Storage 數(shù)據(jù)存?。ㄗ钅荏w現(xiàn)實(shí)踐經(jīng)驗(yàn))select 選存儲(chǔ)結(jié)構(gòu)scheme 細(xì)化數(shù)據(jù)表3.1 SQL V.S NoSQL需要事務(wù)嗎?No,nosql+1
需要豐富的 sql query 嗎?no,nosql+1
想偷懶嗎?tiny url需要寫的代碼不復(fù)雜,nosql+1
qps高嗎?2k,不高。sql+1
scalability 要求多高?存儲(chǔ)和 qps 都不高,單機(jī)都能搞定。sql+1
- sql 需要自己寫代碼來 scale- nosql,這些都幫你做了
是否需要 sequential ID?取決于你的算法
sql 提供 auto_increment 的 sequencetial ID,即 1,2,3nosql 的 ID 不是 sequential3.2 算法long ur 轉(zhuǎn)成一個(gè) 6 位的 short url。給出一個(gè)長(zhǎng)網(wǎng)址,返回一個(gè)短網(wǎng)址。
實(shí)現(xiàn)兩個(gè)方法:
longToShort(url)?把一個(gè)長(zhǎng)網(wǎng)址轉(zhuǎn)換成一個(gè)以http://tiny.url/開頭的短網(wǎng)址shortToLong(url)把一個(gè)短網(wǎng)址轉(zhuǎn)換成一個(gè)長(zhǎng)網(wǎng)址shortToLong(url)把一個(gè)短網(wǎng)址轉(zhuǎn)換成一個(gè)長(zhǎng)網(wǎng)址標(biāo)準(zhǔn):
短網(wǎng)址的key的長(zhǎng)度應(yīng)為6 (不算域名和反斜杠)??捎米址挥衃a-zA-Z0-9]?. 比如:abcD9E[a-zA-Z0-9]?. 比如:abcD9E任意兩個(gè)長(zhǎng)的url不會(huì)對(duì)應(yīng)成同一個(gè)短url,反之亦然。用兩個(gè)哈希表:
一個(gè)是短網(wǎng)址映射到長(zhǎng)網(wǎng)址一個(gè)是長(zhǎng)網(wǎng)址映射到短網(wǎng)址短網(wǎng)址是固定的格式: "http://tiny.url/" + 6個(gè)字符, 字符可任意。
為避免重復(fù), 我們可以按照字典序依次使用, 或者在隨機(jī)生成的基礎(chǔ)上用一個(gè)集合來記錄是否使用過。
使用哈希函數(shù)(不可行)
如取 long url的 MD5 的最后 6 位:
快難以設(shè)計(jì)一個(gè)無(wú)哈希沖突的哈希算法隨機(jī)生成 shortURL+DB去重
隨機(jī)取一個(gè) 6 位的 shortURL,若沒使用過,就綁定到改 long url。
public String long2Short(String url) { while(true) { String shortURL = randomShortURL(); if (!databse.filter(shortURL=shortURL).exists()) { database.create(shortURL=shortURL, longURL=url); return shortURL; } } }public class TinyUrl { public TinyUrl() { long2Short = new HashMap 優(yōu)點(diǎn):實(shí)現(xiàn)簡(jiǎn)單 缺點(diǎn):生成短鏈接的速度,隨著短鏈接越多而越慢 關(guān)系型數(shù)據(jù)庫(kù)表:只需Short key和 long url兩列,并分別建立索引 也可使用 nosql,但需要建立兩張表: 進(jìn)制轉(zhuǎn)換 Base32(微博實(shí)現(xiàn)方案) Base62: 6 位可表示的不同 URL: 優(yōu)點(diǎn):效率高 缺點(diǎn):強(qiáng)依賴于全局的自增 id public class TinyUrl { public static int GLOBAL_ID = 0; private HashMap 因?yàn)橐玫阶栽?id,所以只能用關(guān)系型 DB 表: id主鍵、long url(索引) 如何提高響應(yīng)速度,和直接打開原鏈接一樣的效率。 明確,這是個(gè)讀多寫少業(yè)務(wù)。 緩存需存儲(chǔ)兩類數(shù)據(jù): 利用地理位置信息提速。 優(yōu)化服務(wù)器訪問速度: 優(yōu)化數(shù)據(jù)訪問速度 cache 資源不夠或命中率低 寫操作過多 越來越多請(qǐng)求無(wú)法通過 cache 滿足 多臺(tái)DB服務(wù)器可以優(yōu)化什么? ?解決存不下:存儲(chǔ) ?解決忙不過:qps 那么 tiny url 的主要問題是啥?存儲(chǔ)是沒問題的,重點(diǎn)是 qps。那么,如何 sharding 呢? 垂直拆分:將多張表分別分配給多臺(tái)機(jī)器。對(duì)此不適用,只有兩列,無(wú)法再拆分。 橫向拆分: 若id、shortURL 做分片鍵: ?long2short 查詢時(shí),只能廣播給 N 臺(tái) db 都去查詢 ?為何要查 long2short?避免重復(fù)創(chuàng)建呀 ?若不需要避免重復(fù)創(chuàng)建,則這樣可行 用 long url 做分片鍵: short2long 查詢時(shí),只能廣播給 N 臺(tái) DB 查詢。 4.3.1 分片鍵選擇 若一個(gè) long 可對(duì)應(yīng)多個(gè) short ?使用 cache 緩存所有 long2short ?在為一個(gè) long url 創(chuàng)建 short url 時(shí),若 cache miss,則創(chuàng)建新 short 若一個(gè) long 只能對(duì)應(yīng)一個(gè) short ?若使用隨機(jī)生成算法 ?兩張表,一張存儲(chǔ) long2short,一張存儲(chǔ)short2long ?每個(gè)映射關(guān)系存兩份,則能同時(shí)支持 long2short short2long 查詢 ?若使用 base62 進(jìn)制轉(zhuǎn)換法 ?有個(gè)嚴(yán)重問題,多臺(tái)機(jī)器之間如何維護(hù)一個(gè)全局自增的 id? ?一般關(guān)系型DB只支持在一臺(tái)機(jī)器上實(shí)現(xiàn)這臺(tái)機(jī)器上全局自增的 id 4.4.1 專用一臺(tái) DB 做自增服務(wù) 該 DB不存儲(chǔ)真實(shí)數(shù)據(jù),也不負(fù)責(zé)其他查詢。 為避免單點(diǎn)故障,可能需要多臺(tái) DB。 4.4.2 使用 zk 但使用全局自增 id 不是解決 tiny url最佳方案。Generating a Distributed Sequence Number Hash(long_url)%62作為分片鍵 并將 hash(long_url)%62直接放到 short url 若原來的 short key 是 AB1234,則現(xiàn)在的 short key 是 這樣,就能同時(shí)通過 short、long 得到分片鍵。 缺點(diǎn):DB 的機(jī)器數(shù)目不能超過 62。 所以,最后最佳架構(gòu): web server 和 database 之間的通信。 中心化的服務(wù)器集群和跨地域的 web server 之間通信較慢:如中國(guó)的 Server 需訪問美國(guó)的 DB。 為何不讓中國(guó)的 Server 訪問中國(guó)的 DB 呢? 若數(shù)據(jù)重復(fù)寫到中國(guó) DB,如何解決一致性問題?很難解決! 思考用戶的習(xí)慣: 于是,得到最終架構(gòu): 還可以維護(hù)一份域名白名單,訪問對(duì)應(yīng)地域的 DB。 實(shí)現(xiàn)一個(gè)顧客短網(wǎng)址,使得顧客能創(chuàng)立他們自己的短網(wǎng)址。即你需要在前文基礎(chǔ)上再實(shí)現(xiàn)一個(gè)createCustom。createCustom。 需實(shí)現(xiàn)三個(gè)方法: 注意: 在URLTable里,直接新增一列custom_url記錄對(duì)應(yīng)的custom url是否可行? 不可行!對(duì)于大部分?jǐn)?shù)據(jù),該列其實(shí)都為空,就會(huì)浪費(fèi)存儲(chǔ)空間。 新增一個(gè)表,存儲(chǔ)自定義 URL:CustomURLTable。 創(chuàng)建自定義短鏈接:在 CustomURLTable 中查詢和插入 根據(jù)長(zhǎng)鏈接創(chuàng)建普通短鏈接: 同前文一樣,用兩個(gè)哈希表處理長(zhǎng)網(wǎng)址和短網(wǎng)址之間的相互映射關(guān)系。需額外處理的是用戶設(shè)定的網(wǎng)址與已有沖突時(shí),需返回 "error"。注意:若用戶設(shè)定的和已有恰好相同,則同樣應(yīng)該返回短網(wǎng)址。 public class TinyUrl2 { private HashMap 無(wú)需做任何改動(dòng),直接把custom url當(dāng)short url創(chuàng)建即可! 參考:https://www.zhihu.com/question/29270034 標(biāo)簽:
- 全球新動(dòng)態(tài):短鏈系統(tǒng)設(shè)計(jì)(design tiny url)
- 世界觀熱點(diǎn):5G如何改變工程設(shè)計(jì)
- 天天滾動(dòng):有了 IP 地址,為什么還要用 MAC 地址?
- 酷開創(chuàng)維電腦mini至尊攜臺(tái)式電腦主機(jī)秒殺 助力便捷移動(dòng)辦公
- 環(huán)球看點(diǎn)!5G 技術(shù)如何改變應(yīng)用程序開發(fā)?
- 當(dāng)前信息:隨機(jī)硬件地址、私有 WiFi 地址、隨機(jī) MAC 地址都是些啥
- 今日最新!工信部:我國(guó)光纖化改造全面完成,4G 網(wǎng)絡(luò)覆蓋城鄉(xiāng)、5G 網(wǎng)絡(luò)加快發(fā)展
- 世界即時(shí):聊聊關(guān)于短鏈接那些事
- 天天即時(shí):5G 精確計(jì)時(shí)如何改變我們的自動(dòng)化世界
- 焦點(diǎn)熱門:全球5G物聯(lián)網(wǎng)市場(chǎng)預(yù)計(jì)將迎來高速增長(zhǎng)