低成本伺服器搭建千萬級資料採集系統

發表於2013-08-26

上一篇文章《社會化海量資料採集框架搭建》提到如何搭建一個社會化採集系統架構,講架構一般都比較虛,這一篇講一下如何實戰用低成本伺服器做到日流水千萬級資料的分散式採集系統。

有這樣一個採集系統的需求,達成指標: 需要採集30萬關鍵詞的資料 、微博必須在一個小時採集到、覆蓋四大微博(新浪微博、騰訊微博、網易微博、搜狐微博)。為了節約客戶成本,硬體為普通伺服器:E5200 雙核 2.5G cpu, 4 G DDR3 1333記憶體,硬碟 500G SATA 7200轉硬碟。資料庫為mysql。在這樣的條件下我們能否實現這個系統目標?當然如果有更好的硬體不是這個文章闡述的內容。現通過採集、儲存來說明一下如何實現:

一、採集,目標是在一個小時內把30萬關鍵詞對應的資料從四大微博採集下來,能夠使用的機器配置就是上面配置的普通伺服器。採集伺服器對硬碟沒有太多要求,屬於cpu密集型運算,需耗費一些記憶體。評估下來硬體資源不是瓶頸,看下獲取資料的介面有什麼問題?

  • 1、通過各大微博的搜尋api。就比如新浪微博API針對一個伺服器IP的請求次數,普通許可權限制是一個小時1w次,最高許可權合作授權一個小時4w次。使用應用時還需要有足夠的使用者,單使用者每個應用每小時訪問1000次,最高許可權4w次需要40個使用者使用你的應用。達到30w關鍵詞,至少需要8個應用,如果每個關鍵詞需要訪問3頁,總共需要24個合作許可權的應用。實際操作我們是不可能為這個專案做到開發24個合作許可權的應用,所以這個方式不是很合適。新浪微博API限制參考連結
  • 2、通過各大微博的最新微博收集資料,微博剛推出的時候,各大微博都有微博廣場,可以把最新的微博都收集下來,然後通過分詞,如果出現了30萬關鍵詞中的一個就留下,其他就丟棄掉。不過現在除了騰訊微博和搜狐微博有微博廣場類似的功能,新浪微博和網易微博已經沒有這項功能了。另按照新浪微博之前公佈的資料,註冊使用者已經超過5億,每小時超過1億條微博,如果全量採集對資料儲存是個大的考驗,也需要大量的系統資源,實際採集了一億條,也許就1000w條有用,浪費了9000w條資料的資源。
  • 3、通過各大微博的網頁搜尋,可見即可抓的方式,結合反監控系統模組模擬人的正常行為操作,搜尋30萬關鍵詞資料,使資源最大化利用。為了保證在一個小時採集到,需要採用分散式多執行緒模式抓取,併發採集。併發的時候不能從同一個ip或者同一個ip網段出去,保證對方不會監測到我們的爬蟲。

我們最後採用了第三種方式,目前執行狀況為通過30w關鍵詞搜尋得到的所有微博加在一起總量1000多w條每天,新浪和騰訊最多,新浪微博略勝一籌。使用了6臺普通PC伺服器,就算一臺機器7000元,總共4萬元硬體裝置解決採集硬體問題。整體部署圖為:

milioncrawler1 (1)

二、儲存,採集下來的資料如何處理?首先儲存採集資料是個密集寫的操作,普通硬碟是否能夠支援,mysql資料庫軟體能否支援,未來量突然增加如何應對?再就是評估儲存空間,每天增量這麼多需要耗費大量的儲存資源,如何存放並且易擴充套件。

    • 1、如何儲存。正常來說我們上面配置的伺服器,mysql使用myisam引擎一張表最多20w,使用innodb引擎最多400w,如果超過這個數量,查詢更新速度奇慢。這裡我們採用一個比較取巧的做法,使用mysql的innodb儲存引擎做了一層快取庫,這個快取庫有兩個快取表,每個表只儲存少於300w的資料,有一張表多於300w的資料就切換到另一張表插入直到超過300w再切換回去。切換成功後,把多於300w資料的表truncate掉,記得一定要沒有資料插入的時候再truncate,防止資料丟失。這裡一定要用truncate,不能使用delete,因為delete需要查詢,要用到索引讀寫,並且delete還會寫資料庫log耗費磁碟IO,儲存空間也沒有釋放。truncate和drop是運算元據庫刪除資料比較好的做法。由於有兩個表作為資料插入表,使用資料庫表的自增id並不太合適,需要一個高速的唯一自增Id伺服器提供生成分散式ID。另資料庫完全可以關閉寫事務日誌 ,提高效能,因為抓取的資料當時丟失再啟動抓取就可以了, 這樣資料庫可以保持在一個比較高效能的情況完成插入操作。抓取快取表結果如圖:

milioncrawler2

    • 2、儲存空間。插入後的資料需要儲存下來,不能在超過300w後被truncate掉了。我們需要有個程式在達到300萬時被truncate掉之前把資料同步走,存放到另外一個庫上(我們叫做結果庫,結果庫也是使用innodb引擎)。不過我們每天採集的資料1000多萬,按天遞增,mysql一張表一天就撐爆了,我們這個表不是寫操作密集型,所以結果庫可以儲存多點資料,設定上限500w,但是500萬還是存不下1000萬資料。我們需要對mysql最終結果分庫分表。將資料先按照時間分機器分庫,再按照資料來源分表,比如201301通過hash計算的資料存放在一個機器,201302通過hash計算在另一個機器。到了機器後再按照天或者半天分表,比如表名為 weibo_2013020101 、weibo_2013020112。weibo_2013020101表示2月1日上午一個表,weibo_2013020112表示2月1日下午一個表。光這樣分了還是不夠,1000w/2=500w,經不起壓力擴充套件。我們還需要把表再拆分,比如weibo_2013020101 拆成 weibo_2013020101_1(新浪微博)、weibo_2013020101_2(騰訊微博)、weibo_2013020101_3(網易微博)、weibo_2013020101_4(搜狐微博)。這樣一張表平均就存放 500w/4 = 125w 條資料,遠遠小於500w上限,還可以應對未來突發的增長。再從儲存空間來算,就算一條微博資料為1k,一天 1000w*1k=10G,硬碟500G最多存放50天的資料,所以我們規劃機器的時候可以掛接多一點硬碟,或者增加機器。結果庫分表如圖:

milioncrawler3

按照這樣的架構,我們使用開源免費軟體、低成本伺服器搭建的千萬級資料採集系統在生產運轉良好。

相關文章