c# url短地址壓縮算法與短網址原理的例子,詳細介紹了短網址的映射算法,將長網址md5生成32位簽名串,分為4段,每段8個字節,然后生成短網址,具體見文本實例。
短網址映射算法:
將長網址md5生成32位簽名串,分為4段,每段8個字節;
對這四段循環處理,取8個字節,將他看成16進制串與0x3fffffff(30位1)與操作,即超過30位的忽略處理;
這30位分成6段,每5位的數字作為字母表的索引取得特定字符,依次進行獲得6位字符串;
總的md5串可以獲得4個6位串;取里面的任意一個就可作為這個長url的短url地址;
並不一定說得到的URL是唯一的,但能夠取出4組URL,不會出現太大的重復。
完整代碼:
1 using System; 2 namespace ShortUrlDemo 3 { 4 class Program 5 { 6 static void Main(string[] args) 7 { 8 Random rd = new Random(); 9 10 for (int i = 0; i < 100; i++) 11 { 12 int index = rd.Next(0, 4); 13 var stortUrls = ShortUrl("http://www.freemud.cn"); 14 Console.WriteLine(string.Concat("http://www.freemud.cn/", stortUrls[index])); 15 } 16 Console.Read(); 17 } 18 19 public static string[] ShortUrl(string url) 20 { 21 //可以自定義生成MD5加密字符傳前的混合KEY 22 string key = "Freemud"; 23 //要使用生成URL的字符 24 string[] chars = new string[] 25 { 26 "a", "b", "c", "d", "e", "f", "g", "h", 27 "i", "j", "k", "l", "m", "n", "o", "p", 28 "q", "r", "s", "t", "u", "v", "w", "x", 29 "y", "z", "0", "1", "2", "3", "4", "5", 30 "6", "7", "8", "9", "A", "B", "C", "D", 31 "E", "F", "G", "H", "I", "J", "K", "L", 32 "M", "N", "O", "P", "Q", "R", "S", "T", 33 "U", "V", "W", "X", "Y", "Z" 34 }; 35 //對傳入網址進行MD5加密 36 string hex = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(key + url, "md5"); 37 string[] resUrl = new string[4]; 38 for (int i = 0; i < 4; i++) 39 { 40 //把加密字符按照8位一組16進制與0x3FFFFFFF進行位與運算 41 int hexint = 0x3FFFFFFF & Convert.ToInt32("0x" + hex.Substring(i * 8, 8), 16); 42 string outChars = string.Empty; 43 for (int j = 0; j < 6; j++) 44 { 45 //把得到的值與0x0000003D進行位與運算,取得字符數組chars索引 46 int index = 0x0000003D & hexint; 47 //把取得的字符相加 48 outChars += chars[index]; 49 //每次循環按位右移5位 50 hexint = hexint >> 5; 51 } 52 //把字符串存入對應索引的輸出數組 53 resUrl[i] = outChars; 54 } 55 return resUrl; 56 } 57 } 58 }
結果:

在存放這個URL的數據方面,推薦TTServer。
TTServer數據庫:
Tokyo Cabinet 是日本人 Mikio Hirabayashi(平林幹雄)のページ 開發的一款DBM數據庫(注:大名鼎鼎的DBM數據庫qdbm就是他開發的),該數據庫讀寫非常快。
insert:0.4sec/1000000 recordes(2500000qps),寫入100萬數據只需要0.4秒。
search:0.33sec/1000000 recordes (3000000 qps),讀取100萬數據只需要0.33秒。
可以看到對於字典類型的數據Key/Value的查詢,這個數據庫可以說是我目前見過效率非常高的,況且他如此的小巧,用來對short url/long url的配對再好不過。
該系統使用6個短碼字符來表示任何長度的網址。
有效的字符代碼是ASCII ‘A'到'Z'和'0′的'5′,其中每個字符包含2 ^ 5(32)狀態。 6短碼字符可用於繪制32 ^ 6(1073741824)的網址
首先,需要一個數據庫表來存儲和檢索你映射的網址。
1 CREATE TABLE mappedURL (CREATE TABLE mappedURL( 2 shortCode char (6) not null , 3 lognURL text not null , 4 PRIMARY KEY shortCodeInd (shortCode), 5 );
其次,需要定義一個算法將長的URL映射到短的URL。 算法上面已經介紹過了。
第三,需要創建一個網頁,從數據庫的短網址的映射找到原始的URL,並重定向之。
MD5 已經被破解了,因此不排除攻擊者偽造相同 MD5 的 url 實現惡意目的的可能性。如果不考慮這種情況,md5 collision 的可能性應該是及其低的,估計你我有生之年都看不到。
另外偶不明白“相同的URL每次算出來的鍵值必須都是一樣的”的實際用途會是什么。就算相同的 URL 對應不同的鍵值,一般也不會造成太大的浪費吧?只有 6 位的字母數字組合都可以容納幾十億種變化。
我正是有md5 collision的擔心才問這個問題的。相同的URL要對應相同的鍵值是因為每一個URL地址都需要唯一的對應到數據庫中的一條表數據,但直接用URL來查詢會比較慢,因為:
將要存儲的URL和相關的記錄數據量非常大。
而且有些URL會很長,所以要用text字段。
而如果哈希出唯一的鍵值用varchar來存儲,再根據這個鍵值去查詢就會非常方便快捷。
就像git里面的object hash, 目前基本上不用考慮沖突吧。
bit.ly等url shorter服務是怎么實現的?
需不需要從hash鍵值反向查找url? 如果有這樣的要求, url肯定需要存一個地方, 這樣就可以在沖突的時候進行再散列
MD5是128位hash碼(4個整數,每個整數4個字節)。因此,一個url的MD5碼,有2的128次方(即2e128)個可能。隨意找出來的兩個url的MD5碼相等的可能性,是2e128分之一,即r=2e-128
假如url經MD5后插入數據庫,第一個url插入的不會發生重復,第二個MD5插入時,它跟第一條重復的概率是r。第三條url插入時,重復概率 是2×r,以此類推,第n條插入時發生重復的概率是(n-1)×r。n個MD5碼,其中有兩個重復的概率是這些概率加和。(1+2+3+…+(n- 1))×r = (1/2)×n×(n-1)×r
對於n個MD5碼的集合,存在重復的概率是(1/2)*(n/2e64)e2
因此,只有n大到可以與2e64比擬,才需要考慮它的沖突問題。而2的64次方還是很大的。
所以,只要不是惡意攻擊,一般應用是不太會有collision的。
