長URL連結轉短連結算法

2021-01-11 計算機java編程

引言

很多大型網站都加入了短連結的功能。之所以要是使用短連結,主要是因為微博只允許發140 字,如果連結地址太長的話,那麼發送的字數將大大減少。短連結的主要職責就是把原始連結很長的地址壓縮成只有6 個字母的短連結地址,當我們點擊這6 個字母的連結後,我們又可以跳轉到原始連結地址。

開始以為短連結是按照某種算法把原始連結壓縮為短連結,再根據算法從短連結反算成原始連結的。後來嘗試了下壓縮算法(比如gzip 壓縮算法),發現對於url 這種字符串越是壓縮,長度就越長。通過對壓縮算法的一些了解,發現靠壓縮算法來實現這個功能不太靠譜。

後來在網上找到一個生成算法,該算法主要使用MD5 算法對原始連結進行加密(這裡使用的MD5 加密後的字符串長度為32 位),然後對加密後的字符串進行處理以得到短連結的地址。

原始的算法是C 版本的,這裡我把該算法修改成Java 版本的. 算法的具體代碼如下,代碼中有注釋:

代碼

輸出結果

執行上面代碼的結果如下,會產生4 組6 位字符串,任意一組都可以作為當前字符串的短連結地址。

跳轉原理

當我們生成短連結之後,只需要在表中(資料庫或者NoSql )存儲原始連結與短連結的映射關係即可。當我們訪問短連結時,只需要從映射關係中找到原始連結,即可跳轉到原始連結。

參考1、調用第三方接口自動轉2、springboot 實現長連結轉短連結轉換原理: 將原url通過一系列方式,轉換成6位短碼(只要能不重複,隨便怎麼方式都行);將長短連結存入資料庫,形成一條對應關係;訪問短連結的時候,在資料庫找到對應的長連結,並通過重定向實現原url的訪問;(如果你的轉換方式能過還原,也可以不要資料庫,但必須保證轉換後的短碼不能重複)(代碼部分和正文部分一樣的算法)缺點:這個index的取值範圍額只有32個,永遠不可能是 2、3、6、7、10、11… 。所以自己重新寫一個算法。

3、改進2的算法算法的步驟如下:

對Url進行md5編碼對md5碼進行base64編碼,長度為22剔除base64碼中的『+』和『/』, 取前面的一段,如果位數不夠,用base64碼加上url再進行一次md5,用這個補齊,循環4直到位數滿足短碼的長度需求

網上還有很多算法,比如:自增長算法(這個可能存在增長鎖的問題),隨機數算法。按理來說都是可行的,但是這些算法無法去重,就是可能會出現一個url在對應表中有多條記錄。用上面基於Md5的算法,可以解決這個問題。在發現編碼存在時進一步核實原始url是否一致,如果一致就不是衝突。

最爛的回答

實現一個算法,將長地址轉成短地址。實現長和短一一對應。然後再實現它的逆運算,將短地址還能換算回長地址。

這個回答看起來挺完美的,然後候選人也會說現在時間比較短,如果給我時間我去找這個算法就解決問題了。但是稍微有點計算機或者資訊理論常識的人就能發現,這個算法就跟永動機一樣,是永遠不可能找到的。即使我們定義短地址是100位。那麼它的變化是62的100次方。62=10數字+26大寫字母+26小寫字母。無論這個數多麼大,他也不可能大過世界上可能存在的長地址。所以實現一一對應,本身就是不可能的。

再換一個說法來反駁,如果真有這麼一個算法和逆運算,那麼基本上現在的壓縮軟體都可以歇菜了,而世界上所有的信息,都可以壓縮到100個字符。這~可能嗎。

短 URL 系統是怎麼設計的?

另一個很爛的回答

和上面一樣,也找一個算法,把長地址轉成短地址,但是不存在逆運算。我們需要把短對長的關係存到DB中,在通過短查長時,需要查DB。

怎麼說呢,沒有改變本質,如果真有這麼一個算法,那必然是會出現碰撞的,也就是多個長地址轉成了同一個短地址。因為我們無法預知會輸入什麼樣的長地址到這個系統中,所以不可能實現這樣一個絕對不碰撞的hash函數。

比較爛的回答

那我們用一個hash算法,我承認它會碰撞,碰撞後我再在後面加1,2,3不就行了。

ok,這樣的話,當通過這個hash算法算出來之後,可能我們會需要做btree式的大於小於或者like查找到能知道現在應該在後面加1,2,或3,這個也可能由於輸入的長地址集的不確定性。導致生成短地址時間的不確定性。同樣爛的回答還有隨機生成一個短地址,去查找是否用過,用過就再隨機,如此往復,直到隨機到一個沒用過的短地址。

正確的原理

上面是幾種典型的錯誤回答,下面咱們直接說正確的原理。

正確的原理就是通過發號策略,給每一個過來的長地址,發一個號即可,小型系統直接用mysql的自增索引就搞定了。如果是大型應用,可以考慮各種分布式key- value系統做發號器。不停的自增就行了。第一個使用這個服務的人得到的短地址是xx.xx/0 第二個是 xx.xx/1 第11個是 xx.xx/a 第依次往後,相當於實現了一個62進位的自增欄位即可。

幾個子問題

1. 62進位如何用資料庫或者KV存儲來做?

其實我們並不需要在存儲中用62進位,用10進位就好了。比如第10000個長地址,我們給它的短地址對應的編號是9999,我們通過存儲自增拿到9999後,再做一個10進位到62進位的轉換,轉成62進位數即可。這個10~62進位轉換,你完全都可以自己實現。

2. 如何保證同一個長地址,每次轉出來都是一樣的短地址

上面的發號原理中,是不判斷長地址是否已經轉過的。也就是說用拿著百度首頁地址來轉,我給一個xx.xx/abc 過一段時間你再來轉,我還會給你一個 xx.xx/xyz。這看起來挺不好的,但是不好在哪裡呢?不好在不是一一對應,而一長對多短。這與我們完美主義的基因不符合,那麼除此以外還有什麼不對的地方?

有人說它浪費空間,這是對的。同一個長地址,產生多條短地址記錄,這明顯是浪費空間的。那麼我們如何避免空間浪費,有人非常迅速的回答我,建立一個長對短的KV存儲即可。嗯,聽起來有理,但是。。。這個KV存儲本身就是浪費大量空間。所以我們是在用空間換空間,而且貌似是在用大空間換小空間。真的划算嗎?這個問題要考慮一下。當然,也不是沒有辦法解決,我們做不到真正的一一對應,那麼打個折扣是不是可以搞定?

這個問題的答案太多種,各有各招。這個方案最簡單的是建立一個長對短的hashtable,這樣相當於用空間來換空間,同時換取一個設計上的優雅(真正的一對一)。實際情況是有很多性價比高的打折方案可以用,這個方案設計因人而異了。那我就說一下我的方案吧。

我的方案是: 用key- value存儲,保存「最近」生成的長對短的一個對應關係。注意是「最近」,也就是說,我並不保存全量的長對短的關係,而只保存最近的。比如採用一小時過期的機制來實現LRU淘汰。

這樣的話,長轉短的流程變成這樣:

在這個「最近」表中查看一下,看長地址有沒有對應的短地址,有就直接返回,並且將這個key-value對的過期時間再延長成一小時如果沒有,就通過發號器生成一個短地址,並且將這個「最近」表中,過期時間為1小時所以當一個地址被頻繁使用,那麼它會一直在這個key-value表中,總能返回當初生成那個短地址,不會出現重複的問題。如果它使用並不頻繁,那麼長對短的key會過期,LRU機制自動就會淘汰掉它。當然,這不能保證100%的同一個長地址一定能轉出同一個短地址,比如你拿一個生僻的url,每間隔1小時來轉一次,你會得到不同的短地址。但是這真的有關係嗎?3.如何保證發號器的大並發高可用

上面設計看起來有一個單點,那就是發號器。如果做成分布式的,那麼多節點要保持同步加1,多點同時寫入,這個嘛,以CAP理論看,是不可能真正做到的。其實這個問題的解決非常簡單,我們可以退一步考慮,我們是否可以實現兩個發號器,一個發單號,一個發雙號,這樣就變單點為多點了?依次類推,我們可以實現1000個邏輯發號器,分別發尾號為0到999的號。每發一個號,每個發號器加1000,而不是加1。這些發號器獨立工作,互不幹擾即可。而且在實現上,也可以先是邏輯的,真的壓力變大了,再拆分成獨立的物理機器單元。1000個節點,估計對人類來說應該夠用了。如果你真的還想更多,理論上也是可以的。(雪花算法的優化、美團發號算法的實現)

4.具體存儲如何選擇

這個問題就不展開說了,各有各道,主要考察一下對存儲的理解。對緩存原理的理解,和對市面上DB、Cache系統可用性,並發能力,一致性等方面的理解。

5.跳轉用301還是302

這也是一個有意思的話題。首先當然考察一個候選人對301和302的理解。瀏覽器緩存機制的理解。然後是考察他的業務經驗。301是永久重定向,302是臨時重定向。短地址一經生成就不會變化,所以用301是符合http語義的。同時對伺服器壓力也會有一定減少。

但是如果使用了301,我們就無法統計到短地址被點擊的次數了。而這個點擊次數是一個非常有意思的大數據分析數據源。能夠分析出的東西非常非常多。所以選擇302雖然會增加伺服器壓力,但是我想是一個更好的選擇。

相關焦點

  • Google新PR:以連結距離為基礎的頁面級別
    每個連結Google會計算一個連結長度,連結長度取決於連結本身的特徵和連結所在頁面的特徵,比如頁面上有多少連結,連結的位置,連結文字所用字體等等。所以,同樣是一個連結,連結長度是不一樣的:頁面導出連結越多,連結長度越長。這和原始PageRank思路是一樣的,導出連結越多,每個連結分到的權重越少。
  • Google全站連結是什麼?如何為網站獲取Google全站連結?
    在Google中,一個品牌名稱關鍵詞可以在網站名稱下方顯示2個、4個、6個全站連結。這是一個Google全站連結的示例:Google全站連結是由Google算法選擇的,以提供更佳的用戶體驗,因為用戶無需進行多次點擊即可直接轉到網站首頁。
  • 磁力連結常見的連結形式有哪些 迅雷磁力連結開頭是什麼
    磁力連結常見的連結形式有哪些 迅雷磁力連結開頭是什麼 很多用戶在使用迅雷等下載軟體的時候不知道磁力連結的開頭是什麼樣的,作為比較常用的一個磁力連結
  • 電影連結
    《捉妖戰紀》連結,百度雲盤連結:https://pan.baidu.com/s/1c1STKkC 密碼:gw5w
  • SEO是怎麼改進內部連結的:計算站內PR值
    現代搜尋引擎使用連結來抓取網頁。這些搜尋引擎使用的爬蟲單擊頁面上顯示的每個連結(內部連結和外部連結),然後單擊每個後續頁面上的所有連結,依此類推。這使搜尋引擎可以找到您的頁面並在其索引中對其進行排名。Google之類的搜尋引擎還使用連結數對查詢結果進行排名,並將頁面的所有指向連結視為對該頁面的重要性投票(即PageRank)。
  • 反向連結在2020年還很重要嗎?
    如果您不熟悉SEO優化,那麼您可能不知道反向連結是一種困擾。現在的問題是為什麼?這是因為反向連結是影響百度SEO性能的重要因素。但是,有些人不相信它們是必不可少的(儘管有壓倒性的證據)。在本指南中,我們將向您展示證明反向連結重要性的證據。但首先:什麼是反向連結?當另一個網站連結到您的網站時,就會發生「反向連結」。
  • 一分鐘了解連結,告訴你真正,外、反連結是什麼
    一分鐘了解連結,告訴你真正,外、反連結是什麼SEO建站新站建好之後,如何做SEO優化?一個就是網站的內部更新,另外一個是發布外鏈。外部連結是其中重要的一個環節,因為搜尋引擎只有通過外鏈信息才能認識咱們新站的網站,從而進入自己的網站,爬行並抓取。
  • SEO優化您必須了解的連結「rel」屬性
    通常,您會看到特定連結具有關聯的rel屬性。rel="nofollow"是最常見的用法,您告訴百度和其他搜尋引擎不要「關注」特定連結,並且不得通過該連結傳遞權重。rel屬性的一般語法是:<a rel="nofollow" href="域名">這是一個連結</a>。rel屬性定義了連結資源和當前文檔之間的關係。因此,在上面的示例中,rel屬性定義了包含連結的頁面和連結到的頁面之間的關係。在這種情況下,該關係為nofollow。
  • 阿里巴巴AAAI 18論文CoLink:知識圖譜實體連結無監督學習框架
    引言將不同子知識圖譜上的同一實體信息連結起來(也被稱為用戶身份連結(UIL)問題)通常能得到對該實體的更好和更深度的理解,這通常又能進一步得到更好的商業智能。儘管機器學習算法已經在實體連結問題上得到了廣泛的應用,但訓練數據的標註工作並不簡單。
  • ppt中超連結怎麼添加? 手把手教你在ppt中設置超連結
    ppt中超連結怎麼添加? 手把手教你在ppt中設置超連結時間:2017-08-05 13:37   來源:三聯   責任編輯:沫朵 川北在線核心提示:原標題:ppt中超連結怎麼添加? 手把手教你在ppt中設置超連結 ppt中超連結怎麼添加?
  • 夢境連結為什麼改名夢境重塑
    夢境連結為什麼改名夢境重塑,之前鬧得沸沸揚揚的遊戲下架事件,讓一個本來大受期待的遊戲瞬間銷聲匿跡了,一起來看看本期攻略,為大家帶來關於夢境連結的最新消息。夢境連結可能會夢境重塑重新上線,taptap已經可以預約了,希望這次回來是真的吧,來看看詳細內容吧!
  • 人類大腦最強大的能力:每個神經元可長出8000個連結
    神經元的連結:突觸人類的大腦大概有800億個神經元,神經元與神經元之間,通過突觸「連結」在一起。如下圖所示,這種「連結」並不是實際上連接著的,它是通過形成突觸這樣的結構,從而把神經元上的電信號傳遞到下一個神經元的。
  • 什麼是磁力連結,磁力鏈的原理
    什麼是磁力連結(磁力鏈的原理)2009年時,由於版權的問題以及其他種種原因,很多BT伺服器被迫關閉,這不僅使得很多種子文件從此銷聲匿跡,就連BT Tracker伺服器也停止了解析工作,由此全世界的BT下載進入了一個冰河時代
  • 《賞金奇兵3》女巫連結控制怎麼用 連結控制技能全面解析
    賞金奇兵3女巫連結控制怎麼用?女巫可以說是遊戲中的最強角色了,技能非常出色,馬上帶來玩家「minenike」總結的賞金奇兵3女巫連結控制技能全面解析,一起來看看吧。 賞金奇兵3女巫連結控制技能全面解析 連結 可以連接除伊莎貝爾的貓史黛拉外的任意兩個有生命體徵的哺乳類動物,屍體沒有生命體徵
  • 這份連結,讓你看到疫情期間,大邑教育人的情懷
    2020.2.1大邑縣南街小學召開疫情防控領導小組會議報導平臺:四川新聞網報導連結:http://www.digital.sc.cn/system/20200210/000401760.html▲長按二維碼查看
  • 騙子利用「偽基站」發送詐騙連結
    日期:[2016年06月16日] -- 牡丹晚報 -- 版次:[A12] 騙子利用「偽基站」發送詐騙連結 曹縣警方將嫌犯抓獲
  • 遊戲王決鬥連結遊戲國服下載_遊戲王決鬥連結最新國服下載_18183...
    遊戲王決鬥連結國服是一款有趣的遊戲,喜歡的玩家不要錯過。 遊戲王決鬥連結國服提供了豐富的實時PVP玩法,您可以在排名決鬥中挑戰來自全國各地的決鬥者,成為最強決鬥王!您也可以通過好友決鬥,與朋友來一場輕鬆有趣的娛樂局,重溫童年記憶。
  • 詐騙簡訊再次升級 喜帖簡訊連結暗藏盜號木馬
    昨天(7月7日),讀者郭先生收到了這樣一條簡訊,在簡訊最後還附有一個連結。郭先生點開後發現是讓自己安裝一個程序,他立即起了疑心。巧合的是,他的許多同事也同時收到了這樣一條簡訊。難道真有人請他們喝喜酒嗎?記者採訪了解到,這樣的簡訊是升級後的騙局,目的是套取你的信息。
  • AE和PR動態連結的秘訣
    來源:我是於幹在這篇快速文章中,我們將向你展示如何在Premiere Pro和After Effects之間建立動態連結。幸運的是,大家可以通過稱為動態連結的漂亮功能將Adobe Premiere Pro和After Effects連接起來。
  • BMW聯合創始人做客幣贏超級問答:連結未來數字經濟
    8月26日16:00,幣贏與BMW項目方一起開展的主題為「BMW:連結未來數字經濟」的超級問答ama活動,感謝BMW聯合創始人星辰在百忙之中參加我們的活動,一起分享BMW強大的技術支持和數字經濟生態系統,並就BMW的未來發展規划進入深入探討。