1.前言
長地址:
就是頁面請求實際的地址。如知乎某文章https://www.zhihu.com/question/20103344
短地址:
特定長地址縮短后對應的長度很短的地址,基本上可以理解為一一對應關系
如https://www.zhihu.com/question/20103344的短地址為 http://dwz.date/am7a
備注:
上述地址是由新浪地址轉換平台提供的,對於同一個長地址,不同的轉換平台生成的短地址不一樣,
同一個平台不同時間長成的短地址也可能不一樣
2.使用場景
微博上發送新微博內容時,限制字數為140字,如果需要分享鏈接,那么很長的鏈接會導致內容篇幅縮小,而且url本身也可能超過140個字,所以如果把地址轉換為短地址,那么用戶輸入短地址,看到的是和輸入長地址一樣的頁面信息,那么用戶體驗會變好。
發送推廣短信時超出70字算兩條短信,費用增加,長鏈接也影響用戶體驗
綜上
在特定場景下,需要能夠把長連接轉換為短鏈接
用戶輸入短鏈接的效果和長連接一樣(瀏覽器后台重定向)
短鏈接需要長期有效(或者一定時間內,如1天內有效)
對於同樣的長鏈接,生成的短鏈接需要一樣(或者在一定時間內一樣)
3.實現必要條件(基於本博客所用方案而言的必要條件)
1.有一個獨立的域名系統,用於拼接完整的短鏈接,以后后續反查長鏈接地址
2.一個id發號器(生成樹數字保持唯一),如數據庫的自增序列
4.實現方案
a.將長鏈接字符串插入數據庫,使用sequence遞增序列作為主鍵,然后返回主鍵id
或者是先從發號器取出一個新的id,插入id和長鏈接字符串(兩個字段,且id為主鍵)
b.將主鍵id進行62進制編碼(10數字+26大寫字母+26小寫字母,一般url用這些表示)
c.使用自身域名信息+62進制字符串拼接為完整的url,然后返回
解析:
客戶請求短鏈接時,時間是尋址短鏈接域名發送到我們的系統上,
然后根據鏈接后面的url后綴,轉換為10進制,去數據庫查詢這個主鍵,找出長鏈接,
然后返回給客戶端,且返回碼為301/302(瀏覽器會自動重定向到長鏈接地址,用戶無感知).
5.優化方案
上面有兩個問題未解決:
a.發號器可能會成為瓶頸
b.對於同樣的長鏈接,生成的短鏈接不一樣
解決辦法:
a.發號器問題
可以多用幾個發號器,各自發號不重復即可。
如10個發號器,則發號尾號是1,2,3,4,5,6,7,8,9,0
即發號進制等於發號器的數量,如果發號器只有一個,那么每次發號數增加1.
b. 短鏈接不一樣的問題
方案一:內存存放LinkedHashMap,key為長鏈接,value為短鏈接,
考慮到內存問題,那么只能存放一定數量的鍵值對,使用LRU進行驅逐。
這樣,在一定時間內,某個長鏈接生成的短鏈接一直不變。
方案二:(考慮到要求長鏈接對應的短鏈接要永久一樣)
存入數據庫時,除了唯一id和長鏈接地址外,使用長鏈接生成64位hashcode,然后一並存入數據庫,並且添加索引
下次插入數據庫之前,先查詢hashcode列是否有這個值,有的話則取出比較value是否相等,
這里可能是hash沖突,實際上不是同一個長鏈接,但是使用64位hashcode的話,沖突概率會小很多,
這里使用hashcode做索引,而不是直接使用長鏈接本身,是考慮到長鏈接比較長,作為索引的話,會導致索引層級加深,需要增加額外的磁盤尋址
6.產品舉例
- 新浪:http://sina.lt/
- 百度:http://dwz.cn/
- 0x3:http://0x3.me/
- MRW:http://mrw.so/
新浪長地址轉短地址,使用結果如下:
https://www.zhihu.com/question/20103344 生成的短地址為: am7a
https://www.kanzhun.com/employee/gsl1194828/1587907702/ 生成的短地址為:am7c
使用短鏈接去請求頁面: