1. 程式人生 > >電商搜尋引擎的架構設計和效能優化

電商搜尋引擎的架構設計和效能優化

轉載:https://blog.csdn.net/hu948162999/article/details/78861860

首先,我想說的是電商搜尋引擎和普通的搜尋引擎有很大的差別,因為電商搜尋引擎主要是解決使用者要“買什麼”,而通用搜索引擎主要是解決使用者“搜什麼”。比如同樣搜尋一個詞“百年孤獨”,電商的搜尋肯定是給你推薦這本書的商家,而百度主要是告訴你:《百年孤獨》是一本書。

電商搜尋引擎的特點

眾所周知,標準的搜尋引擎主要分成三個大的部分,第一步是爬蟲系統,第二步是資料分析,第三步才是檢索結果。首先,電商的搜尋引擎並沒有爬蟲系統,因為所有的資料都是結構化的,一般都是微軟的資料庫或者Oracle的資料庫,所以不用像百度一樣用“爬蟲”去不斷去別的網站找內容,當然,電商其實也有自己的“爬蟲”系統,一般都是抓取友商的價格,再對自己進行調整。

第二點,就是電商搜尋引擎的過濾功能其實比搜尋功能要常用。甚至大於搜尋本身。什麼是過濾功能?一般我們網站買東西的時候,搜了一個關健詞,比如尿不溼,然後所有相關品牌或者其他分類的選擇就會呈現在我們面前。對百度而言,搜什麼詞就是什麼詞,如果是新聞的話,可能在時間上會有一個過濾的選項。

第三點,電商搜尋引擎支援各種維度的排序,包括支援好評、銷量、評論、價格等屬性的排序。而且對資料的實時性的要求非常高。對一般的搜尋引擎,只有非常重要的網站,比如一些重量級的入口網站,百度的收錄是非常快的,但是對那些流量很小的網站,可能一個月才會爬一次。電商搜尋對資料的實時性要求主要體現在價格和庫存兩個方面。

電商搜尋引擎另一個特點就是不能丟品,比如我們在淘寶、天貓開了個店鋪,然後好不容易搞了一次活動,但是卻搜不到了,這是無法忍受的。除此之外,電商搜尋引擎與推薦系統和廣告系統是相互融合的,因為搜素引擎對流量的貢獻是最大的,所以大家都希望把廣告系統能跟其融合。當然,還有一點非常重要,就是要保證絕對的高可用,而且不能宕機。

電商搜尋引擎的架構

因為電商搜尋引跟一般的搜尋引擎區別很大,所以在架構的設計上也獨具特色。首先,搜尋引擎的實現方式有很多種,有谷歌、百度、搜狗這種非常大的公司,也有京東、淘寶、噹噹這樣的電商搜尋引擎,很多中小型的電商可能更喜歡用一個開源的搜尋引擎。所以總的來說,主要包括以下這幾種方式:


第一種是“Lucene+自己封裝”,只用來做檢索,然後封裝,後面所有的ES,這兩個是完整的解決方案,而且包括索引所有的東西,只需要部署好業務邏輯,然後查詢結果就可以了。

第二種就是Solr,這是一個高效能,採用Java5開發,基於Lucene的全文搜尋伺服器。同時對其進行了擴充套件,提供了比Lucene更為豐富的查詢語言,同時實現了可配置、可擴充套件並對查詢效能進行了優化,並且提供了一個完善的功能管理介面,是一款非常優秀的全文搜尋引擎。

第三種是ElasticSearch,這是一個基於Lucene的搜尋伺服器。它提供了一個分散式多使用者能力的全文搜尋引擎,基於RESTful web介面。Elasticsearch是用Java開發的,並作為Apache許可條款下的開放原始碼釋出,目前使用的也非常多。

這裡提一下,噹噹的搜尋引擎是自己實現的,。現在,新興的網際網路公司大部分都是使用第一種或者第二種,資料量比較大的一般採用第三種。

電商搜尋引擎標配模組


接下來我想講一下,如果我們自己做一個搜尋引擎的話需要實現哪些功能(上圖是電商搜尋引擎的標準模組),其實不止是電商搜尋引擎,除了通搜的搜尋引擎,其他的搜尋引擎也是使用這樣的標配。


對檢索模組而言,首先是對使用者的意圖進行分析,根據使用者的搜尋詞來進行純演算法的實現。比如使用者的搜尋詞是“黑包包”,其實使用者的本意就是買一個黑色的包,但是這個“包”可以跟別的詞組合在一起,甚至在搜尋結果中會出現“包子”。所以,這就需要query分析系統來做,告訴檢索系統,你需要主要在服裝鞋帽中的分類去找,而不是生鮮食品類。

設計到技術層面,噹噹網使用的是C++。如果構建一個性能好的系統,一些老一點的公司,大家都是在使用C++或者是C語言。不止是噹噹網,其實很多公司都是使用的C或者C++實現的搜尋引擎。

資料更新模組


第二個模組就是資料更新模組,該模組負責生成索引。而資料中心模組主要做的事情,就是將原始的結構化資料,變成一個可供檢索系統使用的搜尋資料庫。當然,資料更新模組和檢索模組是分開還是合併呢?其實從本質上講,都是一堆程式碼,完全可以寫在一個程序裡。當然,也可以分開,通過網路往外輸入,各自都有道理。第一種是簡單粗暴型的,如果是普通電商,像生鮮電商,資料量不大,實時性、季節性很強,就可以把兩個系統用一個程序來完成。但是如果到了百萬、千萬甚至上億級別的話,就不可能部在一臺機器上了。


上圖就是當兩個系統合併在一起的時候,紅色部分就是檢索系統,黃色部分是上游產生資料的系統,如果是淘寶的話,對接就是淘寶的商戶,噹噹網對接是市場部的人員,他們將資料錄入系統,推到資料庫,然後向下進行傳送,最終建立一個索引。

上圖中的藍色部分就是業務邏輯,因為電商的搜尋引擎業務需求量非常高,尤其是現在大家都喜歡用手機進行購物,像手機專享價就是一個新的業務,這也意味著需要一個專用的模組來處理這些商用的邏輯。

此外,就是使用者行為的分析,我們蒐集到的日誌還有其他相關的資料都會存到Hadoop叢集上去,通過離線計算,然後傳給商業模組或者排序模組進行排序和打分,並提供給使用者更好的使用體驗。

出問題是不可避免的!如何解決?

雖然整理來看,設計的思路是非常合理的,但是還是會出現問題。一般而言,一個成熟的電商搜尋系統,它的問題都很集中,要這幾種情況:首先就是Bug,當然這是所有系統都會遇到的問題;第二個就是併發,但是搜尋系統是沒辦法進行分庫分表,所以能做的就是索引切分;最後一點就是監控,包括問題追蹤、日誌系統和監控系統,那麼為了解決這些問題,我們應該怎麼做?

首先,針對Bug問題,只能靠自動化運維去解決(這裡也推薦使用OneAPM工具);第二個就是高併發的問題,目前主要是靠快取和橫向擴充套件。而快取和橫向擴充套件怎麼應用到系統中去,這個很關鍵。很多人也說可以換一種語言,比如講Python換成C++,但實際情況下,換語言並不能解決併發的問題,好的資料結構的設計比換一種語言更能提高效能,所以一般解決高併發問題的也就是快取和橫向擴充套件。

第三個就是使用用FLUME日誌系統(Flume是Cloudera提供的一個高可用的,高可靠的,分散式的海量日誌採集、聚合和傳輸的系統,Flume支援在日誌系統中定製各類資料傳送方,用於收集資料;同時,Flume提供對資料進行簡單處理,並寫到各種資料接受方(可定製)的能力)。其實,Flume會把叢集上每一個節點的日誌全都收集起來,這樣做起來有兩個好處,第一是現場出問題,可以先回滾出Bug,然後進行查詢。第二個就是對日誌進行蒐集,然後做使用者行為分析,檢視使用者點選了多少次,從何處匯入的流量等等,從而便於更好的進行排序。


然後講一下快取的問題。一般搜尋的快取可能分為兩級快取,據我觀察,像搜狗可能是使用頁面級快取,而百度可能用的是索引級的快取。比如在搜狗搜尋一個詞,開始時可能需要40毫秒,然後再搜的話,就可能一下子降到1毫秒。這就是頁面級快取。而百度可能第一次搜尋用了40毫秒,第二次就是25毫秒,它並不是把頁面給快取下來,而是將索引的倒排鏈快取,級別其實是不一樣的。

電商搜尋很多使用的是兩級快取,對於特別熱門的詞彙,我們可以做頁面級快取,而頁面級快取的時間只有15秒到20秒。但是像價格這樣的東西不能快取,需要前臺頁面去反拉價格。第二級就是索引級別的快取,實際上也是自建的一個快取系統。另外,排序也有快取,因為排序的結果不太會有太大的變化。


上圖是噹噹的搜尋架構,這裡有一個叢集是做資料分析的,上面備滿了資料。

首先,叢集之間採用什麼樣的通訊方式?我們主要使用ZMQ(這是一個簡單好用的傳輸層,像框架一樣的一個 socket library,使得 Socket 程式設計更加簡單、簡潔和效能更高。是一個訊息處理佇列庫,可在多個執行緒、核心和主機盒之間彈性伸縮)。原因其實只有一個,就是快,非常快,比較適合資料量比較大的業務。

如何避免冷啟動?

最後就是冷啟動的問題,這個問題是很多電商網站都很頭疼的問題。尤其是隨著電商網站的商品數量達到一定量級的時候,比如已經上億了,像淘寶、天貓的話應該更多。如果重建了一次索引需要啟動,或者新上線了一個業務模組,需要重啟系統,是很麻煩的。

當然,當叢集大了以後有很多方法,比如分開啟動之類的,至於技術嘛,一般索引的載入都是使用Lunix標準的MMAP(MMAP將一個檔案或者其它物件對映進記憶體。檔案被對映到多個頁上,如果檔案的大小不是所有頁的大小之和,最後一個頁不被使用的空間將會清零。MMAP在使用者空間對映呼叫系統中作用很大),這樣啟動速度會很快,但是系統會有預熱時間,前面一些時間的查詢會比較慢

如果資料量不是特別大的話,而且現在記憶體也那麼便宜,完全可以將資料一次性讀入記憶體,因為mmap的操作畢竟效能沒有直接記憶體來得快。

第三種的話,就是儘量減少做全量資料的頻率,避免整個系統的重啟,這需要定期做一下索引的優化,把沒用的索引幹掉。

如果是新上了一個業務模組需要重啟叢集,這樣的事情最好不要發生,這就是架構有問題了,將業務模組變成外部的模組或者外掛進行上線才是正確的,不然每上線一個模組需要重啟叢集,這誰都受不了

轉載:https://blog.csdn.net/hu948162999/article/details/78861860

首先,我想說的是電商搜尋引擎和普通的搜尋引擎有很大的差別,因為電商搜尋引擎主要是解決使用者要“買什麼”,而通用搜索引擎主要是解決使用者“搜什麼”。比如同樣搜尋一個詞“百年孤獨”,電商的搜尋肯定是給你推薦這本書的商家,而百度主要是告訴你:《百年孤獨》是一本書。

電商搜尋引擎的特點

眾所周知,標準的搜尋引擎主要分成三個大的部分,第一步是爬蟲系統,第二步是資料分析,第三步才是檢索結果。首先,電商的搜尋引擎並沒有爬蟲系統,因為所有的資料都是結構化的,一般都是微軟的資料庫或者Oracle的資料庫,所以不用像百度一樣用“爬蟲”去不斷去別的網站找內容,當然,電商其實也有自己的“爬蟲”系統,一般都是抓取友商的價格,再對自己進行調整。

第二點,就是電商搜尋引擎的過濾功能其實比搜尋功能要常用。甚至大於搜尋本身。什麼是過濾功能?一般我們網站買東西的時候,搜了一個關健詞,比如尿不溼,然後所有相關品牌或者其他分類的選擇就會呈現在我們面前。對百度而言,搜什麼詞就是什麼詞,如果是新聞的話,可能在時間上會有一個過濾的選項。

第三點,電商搜尋引擎支援各種維度的排序,包括支援好評、銷量、評論、價格等屬性的排序。而且對資料的實時性的要求非常高。對一般的搜尋引擎,只有非常重要的網站,比如一些重量級的入口網站,百度的收錄是非常快的,但是對那些流量很小的網站,可能一個月才會爬一次。電商搜尋對資料的實時性要求主要體現在價格和庫存兩個方面。

電商搜尋引擎另一個特點就是不能丟品,比如我們在淘寶、天貓開了個店鋪,然後好不容易搞了一次活動,但是卻搜不到了,這是無法忍受的。除此之外,電商搜尋引擎與推薦系統和廣告系統是相互融合的,因為搜素引擎對流量的貢獻是最大的,所以大家都希望把廣告系統能跟其融合。當然,還有一點非常重要,就是要保證絕對的高可用,而且不能宕機。

電商搜尋引擎的架構

因為電商搜尋引跟一般的搜尋引擎區別很大,所以在架構的設計上也獨具特色。首先,搜尋引擎的實現方式有很多種,有谷歌、百度、搜狗這種非常大的公司,也有京東、淘寶、噹噹這樣的電商搜尋引擎,很多中小型的電商可能更喜歡用一個開源的搜尋引擎。所以總的來說,主要包括以下這幾種方式:


第一種是“Lucene+自己封裝”,只用來做檢索,然後封裝,後面所有的ES,這兩個是完整的解決方案,而且包括索引所有的東西,只需要部署好業務邏輯,然後查詢結果就可以了。

第二種就是Solr,這是一個高效能,採用Java5開發,基於Lucene的全文搜尋伺服器。同時對其進行了擴充套件,提供了比Lucene更為豐富的查詢語言,同時實現了可配置、可擴充套件並對查詢效能進行了優化,並且提供了一個完善的功能管理介面,是一款非常優秀的全文搜尋引擎。

第三種是ElasticSearch,這是一個基於Lucene的搜尋伺服器。它提供了一個分散式多使用者能力的全文搜尋引擎,基於RESTful web介面。Elasticsearch是用Java開發的,並作為Apache許可條款下的開放原始碼釋出,目前使用的也非常多。

這裡提一下,噹噹的搜尋引擎是自己實現的,。現在,新興的網際網路公司大部分都是使用第一種或者第二種,資料量比較大的一般採用第三種。

電商搜尋引擎標配模組


接下來我想講一下,如果我們自己做一個搜尋引擎的話需要實現哪些功能(上圖是電商搜尋引擎的標準模組),其實不止是電商搜尋引擎,除了通搜的搜尋引擎,其他的搜尋引擎也是使用這樣的標配。


對檢索模組而言,首先是對使用者的意圖進行分析,根據使用者的搜尋詞來進行純演算法的實現。比如使用者的搜尋詞是“黑包包”,其實使用者的本意就是買一個黑色的包,但是這個“包”可以跟別的詞組合在一起,甚至在搜尋結果中會出現“包子”。所以,這就需要query分析系統來做,告訴檢索系統,你需要主要在服裝鞋帽中的分類去找,而不是生鮮食品類。

設計到技術層面,噹噹網使用的是C++。如果構建一個性能好的系統,一些老一點的公司,大家都是在使用C++或者是C語言。不止是噹噹網,其實很多公司都是使用的C或者C++實現的搜尋引擎。

資料更新模組


第二個模組就是資料更新模組,該模組負責生成索引。而資料中心模組主要做的事情,就是將原始的結構化資料,變成一個可供檢索系統使用的搜尋資料庫。當然,資料更新模組和檢索模組是分開還是合併呢?其實從本質上講,都是一堆程式碼,完全可以寫在一個程序裡。當然,也可以分開,通過網路往外輸入,各自都有道理。第一種是簡單粗暴型的,如果是普通電商,像生鮮電商,資料量不大,實時性、季節性很強,就可以把兩個系統用一個程序來完成。但是如果到了百萬、千萬甚至上億級別的話,就不可能部在一臺機器上了。


上圖就是當兩個系統合併在一起的時候,紅色部分就是檢索系統,黃色部分是上游產生資料的系統,如果是淘寶的話,對接就是淘寶的商戶,噹噹網對接是市場部的人員,他們將資料錄入系統,推到資料庫,然後向下進行傳送,最終建立一個索引。

上圖中的藍色部分就是業務邏輯,因為電商的搜尋引擎業務需求量非常高,尤其是現在大家都喜歡用手機進行購物,像手機專享價就是一個新的業務,這也意味著需要一個專用的模組來處理這些商用的邏輯。

此外,就是使用者行為的分析,我們蒐集到的日誌還有其他相關的資料都會存到Hadoop叢集上去,通過離線計算,然後傳給商業模組或者排序模組進行排序和打分,並提供給使用者更好的使用體驗。

出問題是不可避免的!如何解決?

雖然整理來看,設計的思路是非常合理的,但是還是會出現問題。一般而言,一個成熟的電商搜尋系統,它的問題都很集中,要這幾種情況:首先就是Bug,當然這是所有系統都會遇到的問題;第二個就是併發,但是搜尋系統是沒辦法進行分庫分表,所以能做的就是索引切分;最後一點就是監控,包括問題追蹤、日誌系統和監控系統,那麼為了解決這些問題,我們應該怎麼做?

首先,針對Bug問題,只能靠自動化運維去解決(這裡也推薦使用OneAPM工具);第二個就是高併發的問題,目前主要是靠快取和橫向擴充套件。而快取和橫向擴充套件怎麼應用到系統中去,這個很關鍵。很多人也說可以換一種語言,比如講Python換成C++,但實際情況下,換語言並不能解決併發的問題,好的資料結構的設計比換一種語言更能提高效能,所以一般解決高併發問題的也就是快取和橫向擴充套件。

第三個就是使用用FLUME日誌系統(Flume是Cloudera提供的一個高可用的,高可靠的,分散式的海量日誌採集、聚合和傳輸的系統,Flume支援在日誌系統中定製各類資料傳送方,用於收集資料;同時,Flume提供對資料進行簡單處理,並寫到各種資料接受方(可定製)的能力)。其實,Flume會把叢集上每一個節點的日誌全都收集起來,這樣做起來有兩個好處,第一是現場出問題,可以先回滾出Bug,然後進行查詢。第二個就是對日誌進行蒐集,然後做使用者行為分析,檢視使用者點選了多少次,從何處匯入的流量等等,從而便於更好的進行排序。


然後講一下快取的問題。一般搜尋的快取可能分為兩級快取,據我觀察,像搜狗可能是使用頁面級快取,而百度可能用的是索引級的快取。比如在搜狗搜尋一個詞,開始時可能需要40毫秒,然後再搜的話,就可能一下子降到1毫秒。這就是頁面級快取。而百度可能第一次搜尋用了40毫秒,第二次就是25毫秒,它並不是把頁面給快取下來,而是將索引的倒排鏈快取,級別其實是不一樣的。

電商搜尋很多使用的是兩級快取,對於特別熱門的詞彙,我們可以做頁面級快取,而頁面級快取的時間只有15秒到20秒。但是像價格這樣的東西不能快取,需要前臺頁面去反拉價格。第二級就是索引級別的快取,實際上也是自建的一個快取系統。另外,排序也有快取,因為排序的結果不太會有太大的變化。


上圖是噹噹的搜尋架構,這裡有一個叢集是做資料分析的,上面備滿了資料。

首先,叢集之間採用什麼樣的通訊方式?我們主要使用ZMQ(這是一個簡單好用的傳輸層,像框架一樣的一個 socket library,使得 Socket 程式設計更加簡單、簡潔和效能更高。是一個訊息處理佇列庫,可在多個執行緒、核心和主機盒之間彈性伸縮)。原因其實只有一個,就是快,非常快,比較適合資料量比較大的業務。

如何避免冷啟動?

最後就是冷啟動的問題,這個問題是很多電商網站都很頭疼的問題。尤其是隨著電商網站的商品數量達到一定量級的時候,比如已經上億了,像淘寶、天貓的話應該更多。如果重建了一次索引需要啟動,或者新上線了一個業務模組,需要重啟系統,是很麻煩的。

當然,當叢集大了以後有很多方法,比如分開啟動之類的,至於技術嘛,一般索引的載入都是使用Lunix標準的MMAP(MMAP將一個檔案或者其它物件對映進記憶體。檔案被對映到多個頁上,如果檔案的大小不是所有頁的大小之和,最後一個頁不被使用的空間將會清零。MMAP在使用者空間對映呼叫系統中作用很大),這樣啟動速度會很快,但是系統會有預熱時間,前面一些時間的查詢會比較慢

如果資料量不是特別大的話,而且現在記憶體也那麼便宜,完全可以將資料一次性讀入記憶體,因為mmap的操作畢竟效能沒有直接記憶體來得快。

第三種的話,就是儘量減少做全量資料的頻率,避免整個系統的重啟,這需要定期做一下索引的優化,把沒用的索引幹掉。

如果是新上了一個業務模組需要重啟叢集,這樣的事情最好不要發生,這就是架構有問題了,將業務模組變成外部的模組或者外掛進行上線才是正確的,不然每上線一個模組需要重啟叢集,這誰都受不了