1. 程式人生 > >淺談搜尋引擎技術原理與架構

淺談搜尋引擎技術原理與架構

搜尋引擎是我們非常熟悉的網際網路產品,上網都離不開搜尋,毫無疑問,在pc端,是多數流量的入口。大家都會說,“有問題,百度一下”,當初百度靠這句廣告語,打開了國內很大的市場。

曾經看過一個百度員工寫的段子:“今天一個出租出司機載我去上班,一邊看著百度大廈一邊說,你們百度不就是個框嗎,要這麼多員工幹啥。他說的好有道理,我竟無言以對”。那麼搜尋引擎背後到底是什麼,到底複雜不復雜,這裡為大家一一解答。本文只是簡要介紹一下總體需要的原理,具體的技術原理,我會在後續的文章中深入介紹。

1.索引

輸入一個關鍵詞,就會出現相關的文件。如果這裡有三篇文件,給一個關鍵詞,就通過字串匹配的方法就可以找到包含該關鍵詞的文件,這很簡單。那麼如果有一百篇呢,同樣對這一百篇文章逐個進行搜尋即可,現代計算機對於上百篇文章的檢索還是可以毫秒級的時間完成的。那麼,網路上數以萬計乃至上億的文章,難道也要這樣逐個搜尋嗎。索引就是解決搜尋緩慢的方案,也就是說將每篇文章進行處理,對每一個出現的詞建索引。每個詞對應的列表是包含這個詞的文章的列表,這被稱為倒排索引。於是輸入一個詞,只要查詢這張表,就能很快把包含這個詞的文章給找出來。那如果有多個詞呢,比如,在淘寶上搜索“黃色毛衣”,只要把包含“黃色”的商品和包含“毛衣”的商品求個交集。構建倒排索引是搜尋引擎的基礎。

2.分詞

構建倒排索引的單位是詞,詞代表了語言中最基本的單位。在英文中,可以通過空格對每個詞進行分開,而漢語就相對複雜了,不是通過空格分開的了,需要人通過語義進行分開。上面提到了“黃色毛衣”這個query,可以將“黃色”和“毛衣”分成兩個基本的語言單位。但是,計算機來進行漢語分詞就相對來說比較困難了。好在目前漢語分詞技術已經非常成熟了,也有非常成熟的庫進行呼叫,中科院,復旦等科研機構都對漢語分詞技術研究得很深入。

3.排序

找出這些文章以後,怎麼進行排序,哪篇文章靠前,哪篇文章靠後,也是個問題。我們暫且可以這樣來進行排序,按照相關性來,如果搜尋的query跟文件的標題一樣,這個相關性就相對來說比在正文中出現這些query的文件高。如果詞的順序都一模一樣,那相關性就更高了,如果一字不差,不多字也不少字,當然是相關性最高了。

上述幾個問題,是搜尋的基礎。只要解決了這幾個問題,稍微花幾天功夫,一個計算機系的研究生,就可以把一個簡單的搜尋引擎構建起來了。筆者畫了一下簡單的搜尋引擎的技術架構圖。

那麼搜尋引擎的難點到底在哪呢,為什麼人們都說,Google比百度好呢。

首先,需要明確,搜尋引擎的效果如何評價。迴歸到人們上網的本質意圖,是搜尋到自己需要的文件。如果搜尋引擎能很快地並且很精準地把使用者需要的網頁找出來,那好評率會不斷飆升,業內大家的共識是,每次搜尋使用者花在搜尋引擎上的時間越短,搜尋引擎越好。總結起來,筆者認為,搜尋引擎的評價指標在於:速度、精準性、覆蓋率、時效性。

那麼從這三個指標出發,就為搜尋提出了一些列問題。

首先,從速度來說,毫無疑問,搜尋引擎需要快速對使用者的搜尋進行響應,把最好的結果展現給使用者。我們使用不管哪一款搜尋引擎,拋開網速不說,如果說不能在一秒內返回搜尋結果,那麼基本上就和這一款搜尋引擎拜拜了。高速的搜尋引擎需要依賴以下方面:

1.高併發架構

像百度這樣的搜尋引擎,每秒鐘至少要能扛得住上百萬次搜尋請求。這是工程方面的問題。如果是使用者量級上億的搜尋引擎,需要上百乃至上千的機器來處理請求。針對不同區域的使用者,處理使用者請求的機器都是不同的。

由最開始的電信、移動、聯通的閘道器到搜尋引擎前端機器的流量劃分,再到後端query處理、索引查詢,一個搜尋請求很可能需要經過幾十臺機器的處理,才將結果展現給使用者,而這些流程,在毫秒級時間就完成了。對此,需要有反向代理、負載均衡這樣的技術進行壓力的分流,哪些片區需要多少臺機器,保證這一片的機房不會因為流量過大而奔潰,都是經過工程師的多年運維經驗,預估出來的。並且要考慮過節、突發事件、自然災害對機房的影響等因素,進行多地備份。

這不僅僅是搜尋引擎需要解決的問題,淘寶、微信等任何一款使用者量較大的產品也需要考慮大量使用者訪問帶來的高併發處理。

2.快取技術

每秒鐘上百萬次的搜尋請求,都進行query處理、索引查表、求交集、重排序等工作顯然也是扛不住的,就算有上百萬臺機器來處理,這顯然是很浪費資源的。這樣,快取技術就有用武之地了。搜尋query的熱門程度,大致滿足長尾分佈(http://baike.baidu.com/link?url=JVwZiT_C4WBqFPLPmJRqiuW3m8kmARip_wv4LYCQLWOQoiXfoxfKGaHmjRIlCOBxYzAGD2653qI1uqmmY5t4Na)的,對於一些非常熱門的關鍵詞,可能每秒鐘會出現好多次請求,這樣,如果每次請求都重新處理一次,就是資源的浪費。可以在第一次處理完就把搜尋的結果快取起來,如果再次發生同樣的請求,就可以到快取池裡直接把結果拿出來展現了。不在快取中的結果就需要重新處理,這樣每次需要重新處理的請求都是一些冷門的長尾query。

對於快取的策略,可以採用LRU演算法,按照最近最少使用的方法進行記錄的淘汰,如果系統龐大一點,可以設計多級快取。

3.索引端召回策略

雖然建立了倒排索引,但是如果文章的量級很大,每個term所包含的文章都有上億篇,對於求交和重排都是很耗費時間的。這就需要在索引端就對文章進行粗打分,如果分數都低於某個閾值,就不會將文件參與求交與精排序。那麼另一個問題來了,這個分數怎樣衡量,怎樣的文件才算分數高。這就需要對query進行上下文的處理,結合其他query以及query本身指標進行粗打分。

把網路上的文章全部收錄並且構建索引需要用爬蟲(spider或者crawler)將網路上的文章進行處理。

1.爬蟲策略技術

爬蟲是靠幾個起點網頁出發,通過網頁上的連結導向下一個網頁,順藤摸瓜,將盡可能多的網頁進行獲取,這裡就需要設計到底是深度優先搜尋還是廣度優先搜尋方法來把文章獲取到,同時需要對連結進行分析,比如計算網頁的PageRank值(http://blog.jobbole.com/71431/),計算網頁的權威值。同時,考慮到成本,也不是對所有的網頁進行爬取,可以選擇性挑選一些質量較高的網頁優先進行爬取。至於這個網頁質量如何評價,也是需要工程師不斷在指標檢視下進行優化的。

網頁內容是不斷在變化的,幾個月前,屠呦呦這個名字還不是很火,自從獲得諾貝爾獎以後,很多相關的新聞就出來了。經常上網的人可能會發現,訊息一發布,就很快就能在搜尋引擎上檢索到相關的新聞。從時效性出發,就需要爬蟲對一些更新較頻繁的網頁進行頻繁地訪問,比如說新聞類網站。所以,網站更新頻繁度的指標也是工程師們不斷關注的。某些爬蟲可能側重於優先搜尋更新頻繁度較高的網頁。

那麼同時,爬蟲的訪問會對目標網站帶來壓力,很多網站對有反爬蟲機制,如果爬取地較頻繁,很可能會被目標網站加入黑名單。需要在時效性與可用性之間尋找一個平衡。

如果搜尋引擎能非常“懂你”,並且將最好的結果放在最前面。那是相當友好,相當人性化的。為了做到這一點,需要程式對使用者的query進行語言的理解,同時對使用者的行為進行深入挖掘,例如點選以及停留。筆者認為,精準性是搜尋引擎佔領市場份額最重要的指標。於是也就提出了以下幾個問題:

1.query解析

對於兩個城市型別的query,比如說“北京上海”,可以解析出來,並且將相關火車票和機票的結果返回給使用者。

在地圖檢索中,對於“中關村肯德基”這樣的query,識別出是商圈加上商戶的型別,並將所在商圈的商家都返回給使用者。

在淘寶中,檢索“好看的衣服”,就能識別出“好看”這樣的修飾詞和“衣服”這樣的中心詞,至於好看如何定性,那就是另外一回事了。

另外,類似“北京遇上西雅圖首映時間”這樣的query,就需要實體識別了,因為分詞系統將詞切分的粒度比較小,像“北京遇上西雅圖”這樣的實體,就需要一個智慧的系統來進行抽取了,同時在離線端,也需要將“北京遇上西雅圖”這個實體建立索引。

複雜query的理解,比如說“謝霆鋒的是誰的兒子?”這樣的query,需要用複雜的自然語言處理技術將query進行分析,轉換成相應的格式去知識庫中進行檢索。

針對這些不同的query模式,就可以對query進行分類,不同的query請求不用的伺服器,然後整合自然搜尋的結果,融合起來後進行結果的展示。百度率先推出了阿拉丁平臺,給予商戶一些介面,這樣,搜尋“北京上海”,不用再轉到去哪兒網,就可以把機票火車票結果獲取了。

2.關鍵詞改寫

使用者輸入的query可能由於使用者個人理解記憶或者輸入的手誤打錯,這會嚴重影響搜尋的質量,如果搜尋引擎能判斷出使用者輸入錯誤,並進行糾正,把正確query的結果返回,那使用者體驗會得到更大的提升。對於一些明顯錯誤的query,搜尋引擎給直接把正確query的結果返回。如果是模稜兩可的結果,搜尋引擎會給出一些建議的query。

query改寫系統比較複雜,在離線階段,需要對使用者的搜尋日誌挖掘一些常用易出錯的query term對,或者人工配置一些可能出錯的term對,然後建立一個類似於機器翻譯的模型。在線上階段,按照模型進行候選query的計算。檢索時,對原query檢索的結果打分,結合改寫後query的檢索結果打分進行判斷,到底是給改寫後的query,還是給出一些建議,還是不做任何指示。這就需要進行多次檢索,同時,結果的選擇也可以做成一個分類的模型。

不僅僅是錯誤的糾正,同義詞的擴充套件也是query改寫的一個非常重要的方面,比如說搜尋iPhone需要同時把蘋果手機相關的結果召回,搜尋咖啡廳,同時也需要把咖啡館相關的結果返回。同時,簡稱(北大與北京大學)、別名等改寫也是需要採納的。除了用擴充套件的辦法以外,還可以將query與離線端都進行歸一化,比如說“的哥”全部歸一成“計程車司機”。至於採取哪種策略,需要結合線上的情況進行選擇,或者各種方法的融合。

3.個性化排序

不同人對文章的要求不一樣。喜歡音樂的人搜尋李娜,就希望將歌手李娜的結果排前;喜歡運動的人就希望將運動員李娜的結果排前。傳統的搜尋引擎對於每個人展現的都是一樣的結果,而隨著人們需求的增大,個性化的搜尋就很熱門。這就需要搜尋引擎對檢索結果打分時考慮的不僅僅是相關性的因素,還需要考慮使用者維度的特徵。通過對使用者歷史行為的分析,建立使用者的畫像,每個使用者都可以被量化為一個向量,同時每篇文件也被量化為一個向量,還有使用者與文件互動維度的也被量化為一個向量,比如說使用者曾經點選過此篇文件或者點選過類似的文件。那麼這就是一個機器學習問題。

基於機器學習的排序方法在學術界被稱為learn to rank,目前比較成熟的方法有:pointwise、pairwise、listwise。

4.知識庫的建立

前面提到的類似“謝霆鋒的是誰的兒子?”這樣的query的後面就不是簡單的基於倒排索引的技術了,需要對實體構建知識庫了,在這case中,謝霆鋒就是一個實體,同時謝賢也是一個實體,同時,這兩個實體之間有一個父子關係,為了構建一個強大的知識庫,這都是需要新增的資訊。

於是,類似的問答機器人就出現了,一些號稱能達到幾歲兒童智商的機器人也被炒得很火。你會發現,這樣的機器人知識淵博,深知天文下知地理,其實是靠強大的語音識別技術、語言理解技術、知識庫技術、搜尋技術支撐的。

因此,複雜的搜尋引擎架構圖如下所示:

這些技術可能只是冰山一角,裡面任何一個模組,在大公司裡都是需要幾十人的團隊來完成的,同時還有很多部門負責對這些模組進行有機連線。任何演算法都沒有絕對的好與壞,都是需要認真調研,並對現有的瓶頸進行分析,選擇候選的多個方案進行效能的評估,壓力測試才可上線的。
 

一個商用的搜尋引擎組成部分起來是很複雜的,同時運維和策略都是持久戰,尤其是在移動網際網路快速發展,競爭激烈的今天。這些技術都是國內網很多工程師、教授乃至圖靈獎獲得者的智慧的結晶,一個好的搜尋引擎依賴分散式、平行計算、人工智慧、機器學習等技術。看完此文,你還覺得搜尋引擎簡單嗎,你可以告訴計程車師傅,為什麼百度需要這麼多員工了吧。