<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    LALA  
    日歷
    <2009年6月>
    31123456
    78910111213
    14151617181920
    21222324252627
    2829301234
    567891011

    導航

    留言簿(1)

    隨筆分類(31)

    文章分類(4)

    收藏夾(21)

    搜索

    •  

    積分與排名

    • 積分 - 29818
    • 排名 - 1390

    最新隨筆

    最新評論

    閱讀排行榜

     
    TB級別的網頁容器

    一個高性能的Web爬蟲,必須有一個合適的網頁容器。該容量最大的特點是要能夠通過URL直接存取網頁內容,并且要求有很高的性能,在一個千萬級別的容器中存取一萬次的時間應在1分鐘左右(普通PC上)。
    那么,有什么方式可以實現這個要求?
    首先,我們想到文件系統,將URL編碼(urlEncode,base64或hex都可以)后作為文件名直接存在文件系統的某個目錄下,從而實現通過URL直接存取的目的。但這種方式管理上會有很大的問題(試過在一次刪除十萬個文件的朋友就知道會有多慢),會產生大量的小文件,在某些操作系統上會極大地降低文件系統的性能。
    其次,放在數據庫中,將URL單獨存在一個字段里,為該字段建立索引,也可以實現按URL直接存取的目的,而且性能較好。但實際上這也不合適,幾百萬上千萬的網頁存放在數據庫中,占用近TB的空間,必然要求對數據庫有較大的投資,但從其他網站上采集的網頁使用次數很少,并且極為廉價可再次獲取,因此使用數據庫很不劃算。
    也可以自己實現一個容器,直接管理持久層的裸設備,在裸設備上建立一套通過URL尋址的機制,將會獲得最好的性能。但在容器量較小的情況這樣又顯很麻煩,因此采用拆衷的辦法,在文件系統的基礎上建立一組大文件和一組輔助文件,輔助文件實現通過URL定位該URL代表的網頁在大文件中的位置,從頁實現不隨文件數量增長而性能變化的快速存取。以下將描述一個簡潔的實現。

    我們知道,一個HashMap在容量為10和容量為100000時通過Key存取一個元素的性能基本相當,因此可以在HashMap的基礎上實現一個基于文件系統的FileMap。
    第一步,我們直接照抄HashMap中的散列算法:
    Java代碼
    public static int hash(Object x, int length) { 
        int h = x.hashCode(); 
        h += ~(h << 9); 
        h ^= (h >>> 14); 
        h += (h << 4); 
        h ^= (h >>> 10); 
        return h & (length - 1); 


    假設length等于10000,那么傳入一組URL通過hash()算法返回的值將基本平均分布在這1到10000,而不管這一組URL的具體內容到底是什么(URL之間要有差異,不能都相同或大部分相同,呵呵),這是整個實現最為關鍵的地方。在實際應用中length的值是隨著容量增長而不變化的,每次擴容后都需要將所有URL重新計算散列值,大家可以參考HashMap中的實現。

    第二步:存放文件內容
    實現存放內容的方法:假如現在需要存放一個URL和它的內容,那么必須在value.dat的最后寫入內容長度和內容本身(如果value.dat不存在,則需要先建立一個),并且返回一個內容長度起始字節在value.dat中的起始地址。

    第三步:存放鍵值
    實現存放鍵值的算法:得到內容的起始地址,計算[起始地址+URL]的長度,將該長度和[起始地址+URL]寫入鍵值輔助文件key.dat的最后(如果key.dat不存在,則需要先建立一個),并且返回該長度起始字節在key.dat的地址。

    第四步:存放散列值與鍵值地址的對應關系
    實現存放散列值與鍵值地址對應關系的算法:得到鍵值的起始地址后(地址長度為4字節,即為long類型的長度),通過hash()計算URL的散列值,假設散列值為3000的話,則將該地址寫入地址輔助文件address.idx的第12000-12004個字節。(以后再說散列沖突的情況)

    第五步:取URL內容的
        實現取URL內容的算法:假設URL已經存入FileMap,當需要通過URL取內容時,步驟如上:通過hash()計算URL的散列值,通過散列值從address.idx中取鍵值在key.dat中的地址,通過鍵值中內容在value.dat中的地址,即可取到URL對應的內容了。

    第六步:解決散列沖突
    hash()能將一組URL基本平均地分布在一塊地址上,但不可避免地會出現散列沖突的情況,即多個不同的URL獲得同一個散列值的情況,這時候第一個存入的URL將直接寫入address.idx中散列值對應的地址,其他的URL存入時需要將本身的鍵值地址寫入第一個URL在key.dat的記錄的末尾,以便存取時能夠通過第一個URL找到其他散列值相同的URL,從面解決散列沖突的問題。

    以上六步是實現一個TB級別的容器可以選擇的比較簡潔的過程,實際運用中還需要解決value.dat過大的問題(有時操作系統對文件大小有限制,必須形成value0.data,value1.data,value2.data等一組value文件,從而使得尋址進一步復雜),解決重新散列的問題,解決壓縮存取的問題。

    雖然存取一個URL使用了3個文件,但因address.idx和key.dat的體積都很小,使用時又都是直接定位,并且因頻繁被使用被磁盤的Cache以及操作系統的Cache緩存,時間性能消耗是非常小的。
    posted on 2009-06-04 21:04 Dest 閱讀(212) 評論(0)  編輯  收藏 所屬分類: Java
     
    Copyright © Dest Powered by: 博客園 模板提供:滬江博客
    主站蜘蛛池模板: 久久乐国产综合亚洲精品| 亚洲国产精品线在线观看| 亚洲精品久久无码| 国产国产人免费视频成69堂| 亚洲国产第一页www| 99久久精品免费精品国产| 亚洲嫩草影院在线观看| 亚洲视频在线免费看| 亚洲成人在线免费观看| 午夜福利不卡片在线播放免费| 亚洲宅男精品一区在线观看| 毛片在线免费视频| 99亚洲男女激情在线观看| 亚洲成a人片在线观看久| 久久久久免费视频| 亚洲色大成网站www永久| 亚洲高清中文字幕免费| 直接进入免费看黄的网站| 久久久久久亚洲精品不卡| 永久免费AV无码网站国产| 亚洲精品美女在线观看| 久久久久久99av无码免费网站 | 亚洲av永久无码制服河南实里| 国产精品免费无遮挡无码永久视频 | 亚洲AV综合色一区二区三区| 69精品免费视频| 亚洲性无码AV中文字幕| 亚洲高清最新av网站| 日本免费一区二区久久人人澡| 亚洲国产成人va在线观看网址| 国产无遮挡吃胸膜奶免费看| 怡红院免费全部视频在线视频| 亚洲高清在线mv| 国产在线19禁免费观看| 中文字幕免费在线观看动作大片| 久久亚洲精品无码AV红樱桃| 国产女高清在线看免费观看| 日本免费人成视频在线观看| 久久精品国产亚洲av瑜伽| 亚洲精品高清国产一久久| 国产精品国产免费无码专区不卡|