本文將簡單介紹,如何去完成一個(gè)縮短網(wǎng)址的功能。

Node.js + MySQL + redis版本的源碼地址:github

Demo地址:www.ecool.fun/shortLink

什么是短鏈接

短鏈接,通俗來說,就是將長的URL網(wǎng)址,通過程序計(jì)算等方式,轉(zhuǎn)換為簡短的網(wǎng)址字符串。

大家經(jīng)??梢詮奈⒉┗蛘吒黝悹I銷短信中,看到短鏈接,形式一般類似于 t.cn/xxxxxx,點(diǎn)擊后,就能跳轉(zhuǎn)到對應(yīng)的頁面。

早期短鏈接廣泛應(yīng)用于圖片上傳網(wǎng)站,通過縮短網(wǎng)址URL鏈接字?jǐn)?shù),達(dá)到減少代碼字符串的目的。更便于使用者引用網(wǎng)址,寫入代碼中,節(jié)省字符數(shù)空間。常見于網(wǎng)店圖片分類的使用,因有字符限制,運(yùn)用短鏈接,達(dá)到外鏈圖片的目的,自微博盛行以來,在微博字?jǐn)?shù)有限的特色下,短鏈接也盛行于微博網(wǎng)站,以節(jié)省字?jǐn)?shù),給博主發(fā)布更多文字的空間。

將長鏈接轉(zhuǎn)成短鏈接,一般是為了方便記憶或者傳播。

需要完成的功能

從上面的介紹中,我們得出,縮短網(wǎng)址需要完成以下兩個(gè)功能點(diǎn):

將長網(wǎng)址縮短成短鏈接點(diǎn)擊生成短鏈接,能正常跳轉(zhuǎn)到原來的長網(wǎng)址頁面

全流程設(shè)計(jì)

其實(shí)上述功能點(diǎn)的原理很簡單,簡單描述一下:

用戶輸入長網(wǎng)址,服務(wù)端接收后進(jìn)行處理,并根據(jù)長網(wǎng)址的內(nèi)容,生成一個(gè)短碼,并將映射關(guān)系進(jìn)行存儲(chǔ)。然后根據(jù)短碼拼接出短鏈接,返回給用戶;用戶點(diǎn)擊短鏈接,服務(wù)器端根據(jù)短鏈接中的短碼,查找到對應(yīng)的長網(wǎng)址,并302跳轉(zhuǎn)到對應(yīng)的頁面。

知識(shí)點(diǎn):

為什么要使用302跳轉(zhuǎn),而不是301跳轉(zhuǎn)呢?

整個(gè)流程的設(shè)計(jì)如下圖所示:

可以看到,我用到了MySQL和Redis來存儲(chǔ)長網(wǎng)址和短碼之間的映射關(guān)系。

用MySQL想必大家都能理解,但是為什么要用 Redis 呢,直接用數(shù)據(jù)庫不就好了嗎?

這個(gè)主要是考慮到生成短鏈接,在投放之后的訪問量會(huì)比較大,使用 Redis 緩存后,能有效降低數(shù)據(jù)庫的壓力。

生成短碼的方法

通過上面的全流程設(shè)計(jì),會(huì)發(fā)現(xiàn)主要的問題就是如何通過長網(wǎng)址,去生成對應(yīng)的短碼。

短碼一般是由 [a - z, A - Z, 0 - 9] 這62 個(gè)字母或數(shù)字組成,短碼的長度也可以自定義,但一般不超過8位。比較常用的都是6位,6位的短碼已經(jīng)能有568億種的組合:(26+26+10)^6 = 56800235584,已滿足絕大多數(shù)的使用場景。

目前比較流行的生成短碼方法有:自增id、摘要算法、普通隨機(jī)數(shù)。

自增id

該方法是一種無碰撞的方法,原理是,每新增一個(gè)短碼,就在上次添加的短碼id基礎(chǔ)上加1,然后將這個(gè)10進(jìn)制的id值,轉(zhuǎn)化成一個(gè)62進(jìn)制的字符串。

一般利用數(shù)據(jù)表中的自增id來完成:每次先查詢數(shù)據(jù)表中的自增id最大值max,那么需要插入的長網(wǎng)址對應(yīng)自增id值就是 max+1,將max+1轉(zhuǎn)成62進(jìn)制即可得到短碼。

但是短碼 id 是從一位長度開始遞增,短碼的長度不固定,不過可以用 id 從指定的數(shù)字開始遞增的方式來處理,確保所有的短碼長度都一致。同時(shí),生成的短碼是有序的,可能會(huì)有安全的問題,可以將生成的短碼id,結(jié)合長網(wǎng)址等其他關(guān)鍵字,進(jìn)行md5運(yùn)算生成最后的短碼。

10進(jìn)制轉(zhuǎn)成62進(jìn)制的具體實(shí)現(xiàn):

function string10to62(number) { const chars = '0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ'; const charsArr = chars.split(''); const radix = chars.length; let qutient = +number; let arr = []; do{ let mod = qutient % radix; qutient = (qutient - mod) / radix; arr.unshift(charsArr[mod]); }while(qutient); return arr.join('');}復(fù)制代碼

摘要算法

摘要算法又稱哈希算法,它表示輸入任意長度的數(shù)據(jù),輸出固定長度的數(shù)據(jù)。相同的輸入數(shù)據(jù)始終得到相同的輸出,不同的輸入數(shù)據(jù)盡量得到不同的輸出。

算法思路:

雖然幾率很小,但是該方法依然存在碰撞的可能性,解決沖突會(huì)比較麻煩。不過該方法生成的短碼位數(shù),是固定的,也不存在連續(xù)生成的短碼有序的情況。

普通隨機(jī)數(shù)

該方法是從62個(gè)字符串中隨機(jī)取出一個(gè)6位短碼的組合,然后去數(shù)據(jù)庫中查詢該短碼是否已存在。如果已存在,就繼續(xù)循環(huán)該方法重新獲取短碼,否則就直接返回。

該方法是最簡單的一種實(shí)現(xiàn),不過由于Math.round()方法生成的隨機(jī)數(shù)屬于偽隨機(jī)數(shù),碰撞的可能性也不小。在數(shù)據(jù)比較多的情況下,可能會(huì)循環(huán)很多次,才能生成一個(gè)不沖突的短碼。

具體實(shí)現(xiàn):

// 獲取唯一的Linkasync getShortLink() { const shortLink = this.generateShortLink(); // 查詢數(shù)據(jù)庫中是否存在該鏈接,如果存在,就直接返回 const searchResult = await this.searchByLinkInMySQL(shortLink); if (searchResult && searchResult.length > 0) { // 如果shortLink已經(jīng)存在,就遍歷重新生成 return this.getShortLink(); } return shortLink;}// 生成隨機(jī)的LinkgenerateShortLink() { let str = ''; const arr = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ]; for (let i = 0; i < 6; i++) { const pos = Math.round(Math.random() * (arr.length - 1)); str += arr[pos]; } return str;}復(fù)制代碼

綜上,比較推薦使用第一種方法來實(shí)現(xiàn)短碼的生成

1.《縮短網(wǎng)址 教你怎么實(shí)現(xiàn)縮短網(wǎng)址功能》援引自互聯(lián)網(wǎng),旨在傳遞更多網(wǎng)絡(luò)信息知識(shí),僅代表作者本人觀點(diǎn),與本網(wǎng)站無關(guān),侵刪請聯(lián)系頁腳下方聯(lián)系方式。

2.《縮短網(wǎng)址 教你怎么實(shí)現(xiàn)縮短網(wǎng)址功能》僅供讀者參考,本網(wǎng)站未對該內(nèi)容進(jìn)行證實(shí),對其原創(chuàng)性、真實(shí)性、完整性、及時(shí)性不作任何保證。

3.文章轉(zhuǎn)載時(shí)請保留本站內(nèi)容來源地址,http://f99ss.com/keji/346236.html