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