基於Sphinx構建準實時更新的分佈式通用搜索引擎平臺

前言:

  2008年7月,我寫過一篇文章《基於Sphinx+MySQL的千萬級數據全文檢索(搜索引擎)架構設計》。有很多網友但願閱讀全文,我將該文檔整理了一下,分享出來。文檔解壓後大小爲7.33M,共19頁。

  本站下載地址: http://blog.s135.com/book/sphinx/sphinx_mysql.zip

  新浪下載分流: http://ishare.iask.sina.com.cn/f/6728201.html

  上述文檔架構存在的侷限,我在2008年12月的文章《億級數據的高併發通用搜索引擎架構設計》中已經指出:一是MySQL自己的併發能力有限,在200~300個併發鏈接下,查詢和更新就比較慢了;二是因爲MySQL表的主鍵與Sphinx索引的ID一一對應,從而沒法跨多表創建整站查詢,並且新增長類別還得修改配置文件,比較麻煩;三是由於和MySQL集成,沒法發揮出Sphinx的優點。雖然如此,但對於一些寫入量不大的搜索應用,已經足夠了,或許對不少人會有幫助。

php


  正文:

  在這以後,本人基於《億級數據的高併發通用搜索引擎架構設計》開發的Sphinx分佈式通用站內搜索引擎平臺,已經在生產環境運行9個月以上,通過運營中的不斷完善與改進,目前已造成了一套可擴展的分佈式通用站內搜索引擎框架。CMS、視頻、論壇等產品發生的增、刪、改操做,文本內容實時寫入自行開發的 HTTPSQS 高性能簡單消息隊列服務,經過隊列控制器更新索引和存儲。提供支持XML、JSON的API查詢接口,支持億級數據的索引、分佈式、中文分詞、高亮顯示、自動摘要、準實時(1分鐘內)增量索引更新。

  點擊在新窗口中瀏覽此圖片

  下面是Sphinx新的搜索架構中技術關鍵點實現方式的一些介紹,與你們分享、交流一下:

  一、一元分詞和中文分詞的結合:

  ①、一元分詞位於索引更新模塊。Sphinx索引引擎對於CJK(中日韓)語言(必須是UTF-8編碼)支持一元切分,假設【反恐行動是國產主視角射擊網絡遊戲】這段文字,Sphinx會將其切成【反 恐 行 動 是 國 產 主 視 角 射 擊 網 絡 遊 戲】,而後對每一個字創建反向索引。若是用這句話中包含的字組成一個不存在的詞語,例如【恐動】,也會被搜索到,因此搜索時,須要加引號,例如搜索【"反恐行動"】,就能徹底匹配連在一塊兒的四個字,不連續的【"恐動"】就不會被搜索到。可是,這樣還有一個問題,搜索【"反恐行動遊戲"】或【"國產網絡遊戲"】就會搜索不到。對於這個問題,採用位於搜索查詢模塊的中文分詞來處理。

  sphinx.conf配置文件中關於UTF-8中文一元分詞的配置以下:
html

...省略...
index t_source_main
{
        source                  = t_source_main
        path                    = /data0/search/sphinx/data/t_source_main
        docinfo                 = extern
        mlock                   = 0
        morphology              = none
        min_word_len            = 1
        charset_type            = utf-8
        min_prefix_len          = 0
        html_strip              = 1
        charset_table           = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F
        ngram_len               = 1
        ngram_chars             = U+3000..U+2FA1F
}
...省略...前端



  ②、中文分詞位於搜索查詢模塊。搜索「反恐行動遊戲」、「國產網絡遊戲」,先調用獨立的中文分詞系統,分別切分爲「反恐行動 遊戲」、「國產 網絡遊戲」,這時候,再給以空格分隔的詞語加上引號,去Sphinx搜索【"反恐行動" "遊戲"】或【"國產" "網絡遊戲"】,就能搜索到這條記錄了。中文分詞詞庫發生增、刪、改,無需重建整個Sphinx搜索索引。

mysql


  二、使用自行開發的HTTPSQS(http://code.google.com/p/httpsqs)開源簡單隊列服務程序,來緩衝高併發數據寫入

  新聞、論壇帖子、客服公告、SNS社區等發生的增、刪、改操做,文本內容經過更新接口實時寫入HTTPSQS隊列,再經過隊列控制器更新到Sphinx搜索引擎索引中。

linux


  三、Sphinx不能嚴格按照字段排序的小問題

  若是不想使用權重,只但願嚴格按照時間、主鍵等排序,而匹配模式(Matching modes)又爲非SPH_MATCH_BOOLEAN時(比較經常使用的是SPH_MATCH_ALL、SPH_MATCH_EXTENDED),Sphinx搜索結果在某一頁中的排序會不太準確。例如:按照UNIX時間戳倒序排序,0,20爲第一頁,20,40爲第二頁,第一頁的最小時間戳必定會大於第二頁的最大時間戳,可是,第一頁中的0,20條記錄卻不會嚴格按照時間戳排序,第二頁亦是如此。所以,若是須要精確排序,用戶翻到搜索結果的某一頁,就須要對Sphinx在某一搜索結果頁中的記錄另行再排序,在個人這套搜索架構中,這一再排序操做由search.php查詢接口使用array_multisort()函數處理。通常狀況下,一頁只會顯示5~30條記錄,所以,只對幾十條記錄採用PHP再排序,速度也是很是快的。

sql


  四、隊列控制器中「時間控制」與「數量控制」相結合,實現搜索索引的1分鐘內準實時更新:

  ①、Sphinx 0.9.9生產環境的建索引速度大約在5.5 Mbytes/秒、6400文檔/秒。隊列控制器能夠設置10秒鐘更新一次增量索引,只要Sphinx增量索引數據源的文檔數在38萬之內,就能保證增量索引在1~60秒內獲得更新,這是從「時間」上進行控制。

  ②、爲了不增量索引數據源的文檔數增加到38萬,隊列控制器在增量索引數據源的文檔數超過1萬時,還將激活增量索引合併入主索引的操做,合併完成的文檔將從增量索引數據源中刪除,這是從「數量」上進行控制。

數據庫


  五、自行編寫的「搜索引擎查詢API接口」調用說明:
json

http://xxx.xxx.xxx.xxx/search.php?query=%E9%87%91%E5%B1%B1  (搜索關鍵字。程序可以識別關鍵字是GBK編碼仍是UTF-8編碼,可以識別關鍵字是否進行了URL編碼)
&output=xml  (輸出類型支持:xml 或 json)
&excerpts=1  (是否開啓高亮顯示與文本摘要,1開啓 或 0關閉)
&excerpts_before=<font color=red>  (高亮顯示與文本摘要,若是爲空值則不進行高亮顯示與文本摘要。在匹配的關鍵字前面插入的字符串。)
&excerpts_after=</font>  (高亮顯示與文本摘要,若是爲空值則不進行高亮顯示與文本摘要。在匹配的關鍵字以後插入的字符串。)
&excerpts_limit=256  (高亮顯示與文本摘要,若是爲空值則不進行高亮顯示與文本摘要。摘要最多包含的符號(碼點)數。)
&excerpts_field=c1,c2,c3,c4,c5  (僅對指定的字段進行高亮顯示,其他字段不進行高亮顯示,若是此參數爲空,則默認全部的字符型字段都進行高亮顯示)
&offset=0&limit=20  (至關於SQL語句中的limit 0,20)
&max_matches=30000  (最大搜索結果集數量)
&match_mode=SPH_MATCH_EXTENDED2
&ranking_mode=SPH_RANK_PROXIMITY_BM25
&sort_mode=SPH_SORT_EXTENDED&sort_by=@relevance DESC,u1 ASC,@id DESC  (排序模式:@relevance和@id是內置變量,@relevance表明相關度權值,@id等於search_id,u1爲字段名)
&field_weights=c1,7;c2,1  (權重設置:字段c1的權重爲7,字段c2的權重爲1)
&filter=u1:0_1_6,false;u2:4,true  (整數值過濾器:匹配字段u1等於0、1或6,而且字段u2不等於4的結果集。false表示等於,true表示不等於)
&filter_range=u1:0,100,false;u2:50,90,true  (整數範圍過濾器:字段u1 >= 0而且u1 <= 100,字段u2 < 50而且u2 > 90)
&filter_range=u1:1.23,99.645,false;u2:1034.3,7834.56,true  (浮點數範圍過濾器:字段u1 >= 1.23而且u1 <= 99.645,字段u2 < 1034.3而且u2 > 7834.56)api




  六、搜索結果前臺頁面示例:

  點擊在新窗口中瀏覽此圖片

服務器


  七、同一套服務器平臺與API接口,通用於各種產品:

  示例:

  金山遊戲文章與視頻搜索:http://s.xoyo.com/result.php?w=%E5%89%91%E7%BD%913

  金山遊戲論壇帖子搜索:http://jx3.bbs.xoyo.com/search2.php?srchtxt=%E4%B8%83%E7%A7%80&select=title


 

Tags: sphinx , search , api

 技術大類 » 搜索引擎技術 | 評論(80) | 引用(0) | 閱讀(73203)

燕南天 

2010-2-5 09:30

真的不錯呦~~~~

marker Email 

2010-2-5 10:02

張宴大師,,facebook出了個HipHop,,聽說對性能提高很大,,你寫篇文章分析一下吧

Jason Yu Homepage 

2010-2-5 10:14

很是感謝你技術上的分享。

frankboy 

2010-2-5 10:29

您老何時把那個安裝linux的PPt更新到Centos5.4啊。期待中

glovebx 

2010-2-5 11:49

每次閱讀你的文章受益不淺,感謝分享。

怪物寶 

2010-2-5 13:14

我也想知道大俠對HipHop有什麼意見

dikiking 

2010-2-5 13:24

強烈支持啊。。。

niniwzw 

2010-2-5 13:30

HipHop 估計對通常的小用戶沒有什麼用,通常的網站瓶頸在數據庫 而不是 php。

niniwzw 

2010-2-5 13:42

很是佩服你,開源的東西能玩的這樣溜。

enjoy Homepage 

2010-2-5 15:05

感謝分享《Sphinx搜索引擎架構與使用文檔(和MySQL結合)》,可是有個疑問,增量索引後不須要合併索引嗎?

kylingood Email Homepage 

2010-2-5 15:57

終於等來了。。。。支持兄弟了。。。。哈哈。。。。謝謝開源精神~~~~zangrin

solomon Email 

2010-2-5 16:01

很是感謝 zanzan

luoke 

2010-2-5 16:54

我終於等到這一刻了,絕對的支持。

chris 

2010-2-6 10:23

和Linkedin的Zoie+Bobo-Browser比起來怎麼樣?

心若止水 

2010-2-7 12:24

受益良多 學無止境

liuguoqing 

2010-2-7 15:58

支持   終於等到了

tyler 

2010-2-8 09:22

Sphinx 0.9.9生產環境的建索引速度大約在5.5 Mbytes/秒、6400文檔/秒這個數據應該是跟上下文環境比較有關的,不少狀況下差異很大你用一元分詞去處理中文,索引的數據量應該會大一些吧,搜索效率也會有一些影響

張宴 回覆於 2010-2-8 09:46

個人環境是10000轉的SAS硬盤,若是換成15000轉的硬盤,速度要更快,Sphinx官方給出的索建引速度爲10Mbytes/秒。原版的sphinx一元分詞建立索引速度在5.5M/秒以上,而打了LibMMSeg中文分詞補丁的Sphinx建立索引速度只有300KB/秒,因此採用原版的sphinx 0.9.9可以保證頻繁更新狀況下的索引實時性。一元分詞的索引的數據量會大一些,但能夠經過sphinx分佈式索引來解決搜索效率問題。

newtoushang 

2010-2-8 09:24

大師真是咱們中國開源界的驕傲!但願大師繼續努力,咱們都很支持你!

tyler 

2010-2-8 10:40

不知到你有沒有試過 http://code.google.com/p/sphinx-for-chinese/我我的使用曾達到過7M多/秒,若是數據源的速度能保證,估計索引的速度應該不會太慢

張宴 回覆於 2010-2-8 13:54

沒有測試過。不過,在建立索引時對數據源進行中文分詞,有兩個明顯弊端:一、詞庫的完善度、準確度問題將致使不少記錄搜索不出。例如「俄羅斯民調顯示梅德韋傑夫人氣急升」這句話,假設「梅德韋傑夫」是一個新詞語,在中文分詞詞庫中不存在,這時候,建立索引時的中文分詞就有可能將這句話切分爲「俄羅斯 民調 顯示 梅 德 韋 傑 夫人 氣急 升」。這時候,用戶搜索「梅德韋傑夫」是搜索不到的,由於「夫人」是一個詞語,只有搜「梅德韋傑夫人」才能搜索到,這顯然不合常理;一樣,搜索「人氣急升」也是搜索不到的,前端搜索時被分爲「人氣 急升」兩個詞語,是匹配不到與建立反向索引時的「夫人 氣急 升」三個詞的。二、一旦往中文分詞詞庫中增長、刪除、修改詞語時,整個Sphinx索引須要重建。例如當「劍網3」在原分詞詞庫中不是一個詞語時,建立Sphinx索引時「劍網3網絡版」這句話會按照「劍 網 3 網絡版」進行中文分詞來創建反向索引,而當往Sphinx中文分詞詞庫中增長「劍網3」這個詞語後,用戶搜索「劍網3網絡版」,就會被切分紅「劍網3 網絡版」來搜索,建立索引時和搜索時的中文分詞結果就會不一致,致使搜索不到內容,這時候就必須重建整個Sphinx索引。當中文分詞詞庫須要常常維護(增長、刪除、修改詞語),而Sphinx索引數據又很是大(例如幾十GB~幾百GB),不斷重建整個索引是不可接受的。從下降索引數據量的角度考慮,能夠在在建立索引時爲Sphinx增長二元分詞,來代替中文分詞和Sphinx自帶的一元分詞。在搜索時採用中文分詞。

相關文章
相關標籤/搜索