一個數據爬取和分析系統的演變過程
假設有這樣一個需求,需要你寫一個爬蟲,爬取微博中關于某個話題的討論,然后分析情感,最后用一個網頁來展示分析結果。那么你一開始的數據流程可能是這樣的:
后來,老板發現只有微博一個源不夠,于是又給你加了100000個源。現在你的系統是這樣的:
為了防止太多的線做交叉,我做了一些處理。
一開始你調用 NLP 分析接口的時候,傳入的參數只有爬取內容的正文,但有一天,NLP 研究員希望做一個情感衰減分析。于是你要修改每一個爬蟲,讓每一個爬蟲在調用 NLP 分析接口的時候,都帶上時間參數。這花了你幾天的時間。
你一想,這不行啊,豈不是每次增加修改字段,都要改每一個爬蟲?為了避免動到爬蟲,于是你對系統架構做了一些修改:
現在,爬蟲這邊總是會把它能爬到的全部數據都寫進 Kafka 里面。你的 ETL 程序只挑選需要的字段傳給 NLP 接口進行分析,分析完成以后,寫入數據庫中。程序的處理線條變得清晰了。
你以為這樣就完了?還早呢。
有一天,你發現網頁上的數據很久沒有更新了。說明數據在某個地方停了。現在,你首先去 Kafka 檢查爬蟲的數據,發現爬蟲數據是正常入庫的。那么,說明問題出現在下圖這一塊:
那么,請問是 ETL 在處理數據的時候出現問題導致數據丟失了,還是 NLP 接口出了問題,導致你傳給他的數據沒有返回?還是數據庫不堪重負,寫入數據庫的時候出錯了?
你現在根本不知道哪里出了問題。于是互相甩鍋。
為了避免這個問題,你再一次修改了系統架構:
現在通過檢查 Kafka 的數據,我可以知道 ETL 程序是否正常輸出內容。也可以知道 NLP 分析程序是否正常返回數據。我還可以對比兩邊的數據變化率進行監控。甚至還可以通過監控 Kafka,發現負面內容太多時,及時報警。
當然,這還沒有完,如果還需要發現新的鏈接,并自動抓取,那么又需要增加新的節點。又或者有一些內容需要用瀏覽器渲染,又要增加新的節點……
大家可以看到,數據會反復進出 Kafka,那么它的效率顯然會比直接用爬蟲串聯萬物的寫法慢。但我認為這樣的效率損失是值得的。因為通過把系統拆解成不同的小塊,我們可以對系統運行的每一個階段進行監控,從而能夠更好地了解系統的運行狀態。并且,每一個小塊也能夠更方便地進行維護,無論是修 bug 還是增加新功能,都能減小對其他部分的影響,并且可以提高修復的速度。