如何设计一个短URL地址系统
一、短URL系統(tǒng)的原理:
????????短URL系統(tǒng)的核心是將長(zhǎng)的 URL 轉(zhuǎn)化成短的 URL;在訪問系統(tǒng)時(shí),先使用短地址A訪問短URL系統(tǒng),由短URL系統(tǒng)映射到對(duì)應(yīng)的長(zhǎng)地址B,然后客戶端再重定向(301或者302)到B網(wǎng)址,如下圖所示:
二、短 URL 的好處:
1、鏈接變短,對(duì)于有長(zhǎng)度限制的平臺(tái)發(fā)文,可編輯的文字就變多了
2、短鏈接生成的二維碼更易于識(shí)別,而長(zhǎng)鏈接的二維碼密集難識(shí)別
3、短鏈接更加簡(jiǎn)潔好看且安全,不暴露訪問參數(shù)。
4、能規(guī)避關(guān)鍵詞、域名屏蔽等手段
5、鏈接太長(zhǎng)在有些平臺(tái)上無法自動(dòng)識(shí)別為超鏈接
三、短 URL 系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn):
系統(tǒng)核心實(shí)現(xiàn)思路:使用發(fā)號(hào)器發(fā)號(hào) => 為每個(gè)長(zhǎng)地址分配一個(gè)號(hào)碼ID => 將號(hào)碼與長(zhǎng)地址存放在DB中 => 將號(hào)碼轉(zhuǎn)化成62進(jìn)制,用戶表示最終的短地址并返回給用戶(假設(shè)短地址長(zhǎng)度為8位,62的8次方足夠一般系統(tǒng)使用了) => 用戶使用62進(jìn)制的短地址請(qǐng)求服務(wù) => 將62進(jìn)制的數(shù)轉(zhuǎn)化成10進(jìn)制 => 在DB中尋找對(duì)應(yīng)的長(zhǎng)地址 => 將用戶請(qǐng)求重定向到對(duì)應(yīng)的地址上
1、發(fā)號(hào)器的設(shè)計(jì):
(1)如果是小型系統(tǒng),可使用MySQL的自增主鍵,但是這種方式存在性能問題,要解決該問題,可以通過批量發(fā)號(hào)來解決,提前為每臺(tái)機(jī)器發(fā)放一個(gè)ID區(qū)間 tmp_start_num - tmp_end_num,然后由機(jī)器在自己內(nèi)存中使用 AtomicLong 原子類去保證自增,減少對(duì)DB的依賴,等到區(qū)間即將滿了,再向 DB 請(qǐng)求下一個(gè)區(qū)段的號(hào)碼,然后等區(qū)間滿了,再一次性將記錄保存到DB中,這樣就可以將對(duì)數(shù)據(jù)庫持續(xù)的操作移到代碼中進(jìn)行,并且異步進(jìn)行獲取和寫入操作,保證服務(wù)的持續(xù)高并發(fā)。比如可以每次從數(shù)據(jù)庫獲取10000個(gè)號(hào)碼,然后在內(nèi)存中進(jìn)行發(fā)放,當(dāng)剩余的號(hào)碼不足1000時(shí),重新向MySQL請(qǐng)求下10000個(gè)號(hào)碼,在上一批號(hào)碼發(fā)放完了之后,批量進(jìn)行寫入數(shù)據(jù)庫。
(2)如果是大型系統(tǒng),則可以使用分布式自增主鍵
(3)雪花算法:依賴于系統(tǒng)時(shí)鐘的一致性。如果某臺(tái)機(jī)器的系統(tǒng)時(shí)鐘回?fù)?#xff0c;有可能造成 ID 沖突,或者 ID 亂序。
2、發(fā)號(hào)器的單點(diǎn)問題:
????????可以使用多個(gè)發(fā)號(hào)器,例如實(shí)現(xiàn)兩個(gè)發(fā)號(hào)器,一個(gè)發(fā)單號(hào),一個(gè)發(fā)雙號(hào)。依次類推,我們也可以實(shí)現(xiàn) 1000 個(gè)發(fā)號(hào)器,分別發(fā)尾號(hào)為0到999的號(hào)。每發(fā)一個(gè)號(hào),每個(gè)發(fā)號(hào)器加1000,而不是加1。這些發(fā)號(hào)器獨(dú)立工作,互不干擾即可,這種方式還能解決單點(diǎn)發(fā)號(hào)器性能瓶頸。
3、同一個(gè)長(zhǎng)址多次請(qǐng)求得到的短址不一樣:
????????無論是前面提到的哪種方式,都存在的問題就是同個(gè)長(zhǎng)址多次請(qǐng)求得到的短址是不一樣,因?yàn)槊看味紩?huì)重新為該長(zhǎng)址生成一個(gè)短址。為了實(shí)現(xiàn)長(zhǎng)短鏈接真正意義上的一對(duì)一,我們可以建立一個(gè)長(zhǎng)對(duì)短的 Hashmap,但是需要付出很大的空間代價(jià)。因此我們對(duì)這種方式做一些改變來實(shí)現(xiàn)部分地址的一對(duì)一,比如將最近/最熱門的對(duì)應(yīng)關(guān)系存儲(chǔ)在K-V數(shù)據(jù)庫中,在 Hashmap 中只存儲(chǔ)最近生成的長(zhǎng)對(duì)短的對(duì)應(yīng)關(guān)系,并采用過期機(jī)制實(shí)現(xiàn) LRU 淘汰,從而保證頻繁使用的 URL 的總是對(duì)應(yīng)同一個(gè)短址的,但是不保證不頻繁使用的URL的對(duì)應(yīng)關(guān)系,從而大大減少了空間上的消耗。
????????此外,使用了緩存,也可以加快程序處理速度,將熱門的長(zhǎng)鏈接(需要對(duì)長(zhǎng)鏈接進(jìn)來的次數(shù)進(jìn)行計(jì)數(shù))、最近的長(zhǎng)鏈接(可以使用 Redis 保存最近一個(gè)小時(shí)的數(shù)據(jù))等等進(jìn)行一個(gè)緩存,如果請(qǐng)求的長(zhǎng)URL命中了緩存,那么直接獲取對(duì)應(yīng)的短URL進(jìn)行返回,不需要再進(jìn)行生成操作
4、服務(wù)間的重定向:301 和 302
301永久重定向和 302 臨時(shí)重定向。
- 301永久重定向:第一次請(qǐng)求拿到長(zhǎng)鏈接后,下次瀏覽器再去請(qǐng)求短鏈的話,不會(huì)向短網(wǎng)址服務(wù)器請(qǐng)求了,而是直接從瀏覽器的緩存里拿,減少對(duì)服務(wù)器的壓力。
- 302臨時(shí)重定向:每次去請(qǐng)求短鏈都會(huì)去請(qǐng)求短網(wǎng)址服務(wù)器(除非響應(yīng)中用 Cache-Control 或 Expired 暗示瀏覽器進(jìn)行緩存)
????????使用 301 雖然可以減少服務(wù)器的壓力,但是無法在 server 層獲取到短網(wǎng)址的訪問次數(shù)了,如果鏈接剛好是某個(gè)活動(dòng)的鏈接,就無法分析此活動(dòng)的效果以及用于大數(shù)據(jù)分析了。而 302 雖然會(huì)增加服務(wù)器壓力,但便于在 server 層統(tǒng)計(jì)訪問數(shù),所以如果對(duì)這些數(shù)據(jù)有需求,可以采用 302,因?yàn)檫@點(diǎn)代價(jià)是值得的,但是具體采用哪種跳轉(zhuǎn)方式,還是要結(jié)合實(shí)際情況進(jìn)行選型。
參考文章:
https://www.zhihu.com/question/29270034/answer/46446911
https://cloud.tencent.com/developer/article/1451239
總結(jié)
以上是生活随笔為你收集整理的如何设计一个短URL地址系统的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: JUC多线程:系统调用、进程、线程的上下
- 下一篇: 分布式事务seate-server的do
