亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

基于Java設(shè)計(jì)一個(gè)短鏈接生成系統(tǒng)

 更新時(shí)間:2021年12月09日 08:50:00   作者:清朝程序猿  
相信大家在生活中會(huì)收到很多短信,而這些短信都有一個(gè)特點(diǎn)是鏈接很短。這些鏈接背后的原理是什么呢?怎么實(shí)現(xiàn)的?小編今天就帶你們?cè)敿?xì)了解一下

引言

相信大家在生活中,特別是最近的雙十一活動(dòng)期間,會(huì)收到很多短信,而那些短信都有兩個(gè)特征,第一個(gè)是幾乎都是垃圾短信,這個(gè)特點(diǎn)此處可以忽略不計(jì),第二個(gè)特點(diǎn)是鏈接很短,比如下面這個(gè):

我們知道,短信有些是有字?jǐn)?shù)限制的,直接放一個(gè)帶滿各種參數(shù)的鏈接,不合適,另外一點(diǎn)是,不想暴露參數(shù)。好處無(wú)非以下:

  • 太長(zhǎng)的鏈接容易被限制長(zhǎng)度
  • 短鏈接看著簡(jiǎn)潔,長(zhǎng)鏈接看著容易懵
  • 安全,不想暴露參數(shù)
  • 可以統(tǒng)一鏈接轉(zhuǎn)換,當(dāng)然也可以實(shí)現(xiàn)統(tǒng)計(jì)點(diǎn)擊次數(shù)等操作

那背后的原理是什么呢?怎么實(shí)現(xiàn)的?讓你實(shí)現(xiàn)這樣的系統(tǒng),你會(huì)怎么設(shè)計(jì)呢?【來(lái)自于某鵝場(chǎng)面試官】

短鏈接的原理

短鏈接展示的邏輯

這里最重要的知識(shí)點(diǎn)是重定向,先復(fù)習(xí)一下http的狀態(tài)碼:

分類 含義
1** 服務(wù)器收到請(qǐng)求,需要請(qǐng)求者繼續(xù)執(zhí)行操作
2** 成功,操作被成功接收并處理
3** 重定向,需要進(jìn)一步的操作以完成請(qǐng)求
4** 客戶端錯(cuò)誤,請(qǐng)求包含語(yǔ)法錯(cuò)誤或無(wú)法完成請(qǐng)求
5** 服務(wù)器錯(cuò)誤,服務(wù)器在處理請(qǐng)求的過(guò)程中發(fā)生了錯(cuò)誤

那么以 3 開(kāi)頭的狀態(tài)碼都是關(guān)于重定向的:

  • 300:多種選擇,可以在多個(gè)位置存在
  • 301:永久重定向,瀏覽器會(huì)緩存,自動(dòng)重定向到新的地址
  • 302:臨時(shí)重定向,客戶端還是會(huì)繼續(xù)使用舊的URL
  • 303:查看其他的地址,類似于301
  • 304:未修改。所請(qǐng)求的資源未修改,服務(wù)器返回此狀態(tài)碼時(shí),不會(huì)返回任何資源。
  • 305:需要使用代理才能訪問(wèn)到資源
  • 306:廢棄的狀態(tài)碼
  • 307:臨時(shí)重定向,使用Get請(qǐng)求重定向

整個(gè)跳轉(zhuǎn)的流程:

1.用戶訪問(wèn)短鏈接,請(qǐng)求到達(dá)服務(wù)器

2.服務(wù)器將短鏈接裝換成為長(zhǎng)鏈接,然后給瀏覽器返回重定向的狀態(tài)碼301/302

301永久重定向會(huì)導(dǎo)致瀏覽器緩存重定向地址,短鏈接系統(tǒng)統(tǒng)計(jì)訪問(wèn)次數(shù)會(huì)不正確

302臨時(shí)重定向可以解決次數(shù)不準(zhǔn)的問(wèn)題,但是每次都會(huì)到短鏈接系統(tǒng)轉(zhuǎn)換,服務(wù)器壓力會(huì)變大。

3.瀏覽器拿到重定向的狀態(tài)碼,以及真正需要訪問(wèn)的地址,重定向到真正的長(zhǎng)鏈接上。

從下圖可以看出,確實(shí)鏈接被302重定向到新的地址上去,返回的頭里面有一個(gè)字段Location就是所要重定向的地址:

短鏈接怎么設(shè)計(jì)的

全局發(fā)號(hào)器

肯定我們第一點(diǎn)想到的是壓縮,像文件壓縮那樣,壓縮之后再解壓還原到原來(lái)的鏈接,重定向到原來(lái)的鏈接,但是很不幸的是,這個(gè)是行不通的,你有見(jiàn)過(guò)什么壓縮方式能把這么長(zhǎng)的數(shù)字直接壓縮到這么短么?事實(shí)上不可能。就像是Huffman樹(shù),也只能對(duì)那種重復(fù)字符較多的字符串壓縮時(shí)效率較高,像鏈接這種,可能帶很多參數(shù),而且各種不規(guī)則的情況都有,直接壓縮算法不現(xiàn)實(shí)。

那https://dx.10086.cn/tzHLFw與https://gd.10086.cn/gmccapp/webpage/payPhonemoney/index.html?channel=之間的裝換是怎么樣的呢?前面路徑不變,變化的是后面,也就是tzHLFw與gmccapp/webpage/payPhonemoney/index.html?channel=之間的轉(zhuǎn)換。

實(shí)際也很簡(jiǎn)單,就是數(shù)據(jù)庫(kù)里面的一條數(shù)據(jù),一個(gè)id對(duì)應(yīng)長(zhǎng)鏈接(相當(dāng)于全局的發(fā)號(hào)器,全局唯一的ID):

id url
1 gd.10086.cn/gmccapp/web…

這里用到的,也就是我們之前說(shuō)過(guò)的分布式全局唯一ID,如果我們直接用id作為參數(shù),貌似也可以:https://dx.10086.cn/1,訪問(wèn)這個(gè)鏈接時(shí),去數(shù)據(jù)庫(kù)查詢獲得真正的url,再重定向。

單機(jī)的唯一ID很簡(jiǎn)單,用原子類AtomicLong就可以,但是分布式的就不行了,簡(jiǎn)單點(diǎn)可以用 redis,或者數(shù)據(jù)庫(kù)自增,或者可以考慮Zookeeper之類的。

id 轉(zhuǎn)換策略

但是直接用遞增的數(shù)字,有兩個(gè)壞處:

  • 數(shù)字很大的時(shí)候,還是很長(zhǎng)
  • 遞增的數(shù)字,不安全,規(guī)律性太強(qiáng)了

明顯我們平時(shí)看到的鏈接也不是數(shù)字的,一般都是大小寫(xiě)字母加上數(shù)字。為了縮短鏈接的長(zhǎng)度,我們必須把id轉(zhuǎn)換掉,比如我們的短鏈接由a-z,A-Z,0-9組成,相當(dāng)于62進(jìn)制的數(shù)字,將id轉(zhuǎn)換成為62進(jìn)制的數(shù)字:

public class ShortUrl {
 
    private static final String BASE = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
    public static String toBase62(long num) {
        StringBuilder result = new StringBuilder();
        do {
            int i = (int) (num % 62);
            result.append(BASE.charAt(i));
            num /= 62;
        } while (num > 0);
 
        return result.reverse().toString();
    }
 
    public static long toBase10(String str) {
        long result = 0;
        for (int i = 0; i < str.length(); i++) {
            result = result * 62 + BASE.indexOf(str.charAt(i));
        }
        return result;
    }
 
    public static void main(String[] args) {
        // tzHLFw
        System.out.println(toBase10("tzHLFw"));
        System.out.println(toBase62(27095455234L));
    }
}

id轉(zhuǎn) 62位的key 或者key裝換成為id都已經(jīng)實(shí)現(xiàn)了,不過(guò)計(jì)算還是比較耗時(shí)的,不如加個(gè)字段存起來(lái),于是數(shù)據(jù)庫(kù)變成了:

id key url
27095455234 tzHLFw gd.10086.cn/gmccapp/web…

但是這樣還是很容易被猜出這個(gè)id和key的對(duì)應(yīng)關(guān)系,要是被遍歷訪問(wèn),那還是很不安全的,如果擔(dān)心,可以隨機(jī)將短鏈接的字符順序打亂,或者在適當(dāng)?shù)奈恢眉由弦恍╇S機(jī)生成的字符,比如第1,4,5 位是隨機(jī)字符,其他位置不變,只要我們計(jì)算的時(shí)候,將它對(duì)應(yīng)的關(guān)系存到數(shù)據(jù)庫(kù),我們就可以通過(guò)連接的key找到對(duì)應(yīng)的url。(值得注意的是,key必須是全局唯一的,如果沖突,必須重新生成)

一般短鏈接都有過(guò)期時(shí)間,那么我們也必須在數(shù)據(jù)庫(kù)里面加上對(duì)應(yīng)的字段,訪問(wèn)的時(shí)候,先判斷是否過(guò)期,過(guò)期則不給予重定向。

性能考慮

如果有很多短鏈接暴露出去了,數(shù)據(jù)庫(kù)里面數(shù)據(jù)很多,這個(gè)時(shí)候可以考慮使用緩存優(yōu)化,生成的時(shí)候順便把緩存寫(xiě)入,然后讀取的時(shí)候,走緩存即可,因?yàn)橐话愣替溄雍烷L(zhǎng)鏈接的關(guān)系不會(huì)修改,即使修改,也是很低頻的事情。

如果系統(tǒng)的id用完了怎么辦?這種概率很小,如果真的發(fā)生,可以重用舊的已經(jīng)失效的id號(hào)。

如果被人瘋狂請(qǐng)求一些不存在的短鏈接怎么辦?其實(shí)這就是緩存穿透,緩存穿透是指,緩存和數(shù)據(jù)庫(kù)都沒(méi)有的數(shù)據(jù),被大量請(qǐng)求,比如訂單號(hào)不可能為-1,但是用戶請(qǐng)求了大量訂單號(hào)為-1的數(shù)據(jù),由于數(shù)據(jù)不存在,緩存就也不會(huì)存在該數(shù)據(jù),所有的請(qǐng)求都會(huì)直接穿透到數(shù)據(jù)庫(kù)。如果被惡意用戶利用,瘋狂請(qǐng)求不存在的數(shù)據(jù),就會(huì)導(dǎo)致數(shù)據(jù)庫(kù)壓力過(guò)大,甚至垮掉。

針對(duì)這種情況,一般可以用布隆過(guò)濾器過(guò)濾掉不存在的數(shù)據(jù)請(qǐng)求,但是我們這里id本來(lái)就是遞增且有序的,其實(shí)我們范圍大致都是已知的,更加容易判斷,超出的肯定不存在,或者請(qǐng)求到的時(shí)候,緩存里面放一個(gè)空對(duì)象也是沒(méi)有問(wèn)題的。

到此這篇關(guān)于基于Java設(shè)計(jì)一個(gè)短鏈接生成系統(tǒng)的文章就介紹到這了,更多相關(guān)Java短鏈接生成系統(tǒng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論