這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
一個go語言實現的短連結服務
首先,部落格轉移到 wusay.org 了,去年沒交費,部落格都沒了。。。剛剛恢複過來,以前的文章沒了,慢慢補吧。
什麼是短連結服務
大家都用過新浪微博的短串連吧,就是t.cn後面一串不知道是什麼的數,然後跳轉到一個新頁面去,具體什麼是短串連請大家自行腦補,在這裡,目前有很多提供短串連的地方,比如狼廠的短串連服務,還有提供很多短連結的線上服務,比如這個,能產生很多地方的短串連。
巴特,作為一個程式員,我們不止需要一個端連結服務,我需要自己實現一個短串連服務,因為一般的公用的短串連都有token要求,每天產生的連結也有限制,當你需要產生大量短串連的時候就比較麻煩了。
所以,我實現了一個短串連服務。
短串連的原理
很多人一定想的是短串連是通過一定的演算法將長連結變成短串連的,然後訪問的時候再還原,恩,非常高大上,但是仔細想想,怎麼可能,那得多牛逼的壓縮演算法,多長的url都可以壓縮為幾個位元組,而且還能還原,還是無損壓縮。
所以,實際上,短串連產生核心就兩個字:數數,就是不停的自增一個數,然後有個表儲存每個數和原始連結的對應關係,訪問短串連的時候將原是串連取出來。
知道了原理就好弄了,最簡單的辦法,就是用一個數組來儲存,數組的索引就是短連結,數組的值就是原始連結,恩,完美,由於數組下標是短連結,那麼擷取短連結的時間複雜度是O(1),同時產生短連結的時間複雜度也是O(1)
短連結服務的實現
實現一個短連結服務,用數組固然可能,但也顯得太LOW了吧,所以為了實現這個服務,從以下幾個部分來實現。
首先,給兩個概念
- 解析短連結,就是請求是短串連,返回一個跳轉的原始連結
- 產生短連結,就是有個長連結,返回產生的短連結
儲存
持久化的部分使用Redis資料庫來實現,很明顯,key-value的結構很適合存在Redis中
這部分主要在 shortlib/RedisAdaptor.go中
計數器
數數的功能可以用Redis的自增功能實現,這樣也保證了原子性,同樣這部分也可以自己實現,因為go語言開線程很容易,專門開一個線程實現這個功能,通過channl來接受請求,保證是串列的就行了,不就是數數嘛,大家都會
這部分在shortlib/RedisAdaptor.go和shortService/CountThread.go中,具體實現的時候通過設定檔的參數,返回一個高階函數,調用的時候自動分配到不同的函數實現。
快取服務
Redis固然很快,但是我們還需要更快,要是熱門資料存在記憶體中就更快了,而且還有個問題,就是熱門的url要是有人不停的申請短串連會造成浪費,為了防止這個問題,自己實現了一個LRU模組,解析短連結的時候,命中了話直接返回結果,否則從Redis返回資料,如果是申請短連結的話,如果在LRU中,那不再重建短連結了。
這部分主要在 shortlib/LRU.go中。
對外服務
這一部分用的go的http架構,很容易實現高並發,沒啥好說的,現在編程高並發不是問題了,連語言都內建這架構了。
這部分包括shortlib/Router.go , shortService/OriginalProcessor.go,shortService/ShortProcessor.go 這幾個檔案。
代碼位置
具體可以參考github,代碼已經傳上來了,800多行代碼,沒多少,感興趣的可以自己去看看,歡迎提交BUG
效能測試還沒做,等把代碼全完成以後再測測效能。