短網址服務開發關鍵問題與解決方案
一、背景分析
二維碼的出現使資源傳輸由原來的USB拷貝轉變為二維碼掃描訪問或下載。為下載資源提供短網址服務,需將短網址生成二維碼。資源數據量預計可達10億級別,日新增數據1000萬左右,每秒并發訪問數預計2000個連接,響應時間在0.1秒以內。
二、基本原理
將原始地址轉換為短網址
原始網址→網址縮短→短網址
將短網址轉換為原始網址
短網址→短網址還原→原始網址
關鍵問題
將原始地址轉換為不重復的6位地址標志,海量數據的高并發讀寫。
三、項目實現
短網址實現方案
實現短網址服務,首先要將海量的鏈接數據轉化為不重復的6位字符。
(1)哈希算法。哈希算法相對簡單,具體算法如下:
①將原網址md5轉換成32位哈希碼,分為4段,每段8字節。
②對這四短網址進行循環處理,取8個字節,將其看成16進制串與0x3fffffff(30位1)與操作,即超過30位的忽略處理。
③將30位生成6段,每5位數字作為字母表在索引取得特定字符,依次進行獲取6位字符串。
④總的md5串可以獲得4個6位串,取任意一個就可作為這個長url的短url地址。這種方法實現起來簡單,但是有較高的重復度。
(2)62位字符表示。把數字和字符組合成一定的映射,就可以產生唯一的字符串,再利用洗牌算法,把原字符串打亂后保存,對應位置的組合字符串就會是無序的組合。
大數據存儲解決方案
在本項目中,主要存儲數據有資源下載地址及引用頁地址,預估資源下載地址長度為150個字符,引用頁地址長度為50字符,兩者存起來共200字符,再加上數據庫自身結構占用的空間及其他信息,如時間、ID等,存儲一條數據最少需要250個字節。從當前訪問量來看,預計數據將達到10億條。
總數據量 = 250 * 10^9 /(1024*1024*1024)= 230G 當前采用的是mysql架構, 10億條數據遠遠超過了其處理能力。因此要對數據庫進行分庫分表,將表大小限定為10萬條數據,每個數據庫1000張表,數據庫隨著數據的增長而擴展,表中的ID進行自增長,通過數據庫ID、表ID、數據ID三者就可以唯一確定條數據,將這個值轉換成62進制就得出了唯一的短鏈接地址。
合成ID算法代碼:($database_id*self::database_tables*self::table_rows)+$row_id+ ($table_id*self::table_rows);
每個數據庫將存儲1000*100000=1億條數據,數據將分布在10臺機器上,10臺機器將分解高峰階段的每秒2000個并發讀寫操作。這種算法在初期可能會對單臺機器造成過載,可采用逐步加壓的方式,當數據庫服務器增多后可全部開放。
高并發解決方案
應對每秒2000次的并發訪問需要服務器具有快速的讀寫及負載均衡能力,主要需要解決兩方面的問題:用戶在創建短網址時,需確認該資源沒有創建過;當用戶在訪問一個短網址時,服務器需快速響應。從數據庫直接讀取無法滿足速度需求,同時會造成服務器過載導致系統崩潰。因此,需要將資源url放到內存中,使用內快進行快速讀取。
關鍵問題解決方式
(1)問題一解決方案。由于數據是先有ID后有短網址,無法通過資源地址反查到短網址,因此,需要使用一個內存映射,將資源與短網址(數據ID)聯系起來。操作流程:原始網址→16字節長度的原始二進制md5→從redis中查找是否存在數據ID→從內存緩存或數據庫中取出數據→判斷數據庫中的地址是否與原網址相同→不同則插入數據庫中,建立16字節長度原始二進制md5與數據ID建立聯系存入redis中。
(2)問題二解決方案。將熱數據放入緩存中,減輕數據庫負載,限制一天過期時間,可以防止內存使用過大。操作流程:短網址→查找內存→未找到將短網址轉為ID→從數據庫中查找→存入緩存→返回數據。
四、小結
短網址服務是一個比較復雜的項目,生成短6位短碼是關鍵點,采用數據ID遞增進行62位轉換的方式,可簡單有效地實現需求。