金沙數(shù)據(jù)-大話搜索引擎第一季之初遇搜索(一)
時(shí)間:2023-03-20 07:12:01 | 來(lái)源:電子商務(wù)
時(shí)間:2023-03-20 07:12:01 來(lái)源:電子商務(wù)
本季內(nèi)容概覽:大概會(huì)花費(fèi)4篇左右的文章為大家講解一個(gè)普適率80%左右的垂直搜索引擎,內(nèi)容涵蓋需求分析、架構(gòu)設(shè)計(jì)、模塊切分、各種填坑、效果評(píng)測(cè) 直至上線運(yùn)行。
本篇知識(shí)點(diǎn)概覽:搜索需求分析、架構(gòu)設(shè)計(jì)、功能塊切分
一、放水篇(如果時(shí)間少請(qǐng)直接跳過(guò)閱讀 二、干貨篇 特別聲明:如果有時(shí)間建議放水篇也閱讀一下,無(wú)水萬(wàn)物枯萎凋零 搜索亦然)
2009下半年由于長(zhǎng)期的瘋狂加班身體開始抱恙,到最后幾乎成了藥罐子 每月3000元的工資3500元的藥, 拿現(xiàn)在來(lái)說(shuō)當(dāng)時(shí)也算是活雷鋒了吧!盡管領(lǐng)導(dǎo)一再挽留甚至開出可以讓在家修養(yǎng)半年再回來(lái)工作的條件,最后考慮來(lái)考慮去還是感覺(jué)命更重要一些,于是帶著對(duì)這家?guī)掖蜷_程序世界和服務(wù)2年多的企業(yè)軟件公司的滿懷歉意選擇了say goodbye。
在家休息了兩個(gè)月,身體快恢復(fù)的差不多的時(shí)候也馬上快年關(guān)了。 為了過(guò)年不做無(wú)業(yè)游民,于是開始四處投簡(jiǎn)歷參加面試。大帝都之大往往一天跑下來(lái)只能面試兩家公司,不過(guò)有一天效率奇高上午就跑了兩家公司?;丶艺寐愤^(guò)第二天約的要面試的一家小公司,于是抱著試試看的心理給hr打了個(gè)電話能不能提前來(lái)面一下,結(jié)果hr和技術(shù)負(fù)責(zé)人溝通了一下很爽快的答應(yīng)了。(這么好的hr想必今天已大富大貴了吧)
只有兩道簡(jiǎn)單的算法題,記得一道是給一個(gè)字符串不用api自己寫代碼實(shí)現(xiàn)去掉指定的字符,另一道是給一個(gè)字符串不用api自己寫代碼實(shí)現(xiàn)去掉指定的字符串?;揪褪亲约簩?shí)現(xiàn)java的replace方法?;厝サ漠?dāng)天晚上就給了offer。我好長(zhǎng)一段時(shí)間以為自己面的不錯(cuò)得到了這個(gè)offer,后來(lái)才發(fā)現(xiàn)兩道題目只答對(duì)了第一道,另外一道根本沒(méi)考慮去除掉這種情況 AABCBC字符串中去掉ABC字符串,因?yàn)橹虚g的ABC去掉后前后字符串連接起來(lái)又可能形成了ABC!后來(lái)更知道之所以能被錄用不是因?yàn)槲掖鸬亩嗪?,而是前面的幾個(gè)兄弟答的更差。如今回想起來(lái)仍然感謝前面幾位不知名的兄弟高抬貴手,讓我誤打誤撞的進(jìn)入搜索這個(gè)行業(yè)。
這家小公司我們姑且稱為A公司吧,其實(shí)進(jìn)去后發(fā)現(xiàn)并沒(méi)有我想象的那么小,公司整體也上百號(hào)人了,主打在線訂餐,從03年發(fā)展到09年已經(jīng)當(dāng)仁不讓的成為北方區(qū)在線訂餐的龍頭老大。(當(dāng)時(shí)大批的團(tuán)購(gòu)網(wǎng)站還都沒(méi)有興起,這塊幾乎是一兩家獨(dú)大的狀態(tài)),A公司的搜索當(dāng)時(shí)是使用的第三方的銀杏搜索,效率和效果都糟糕的很,很多公司特定的需要也沒(méi)法實(shí)現(xiàn),迫切的需要自己公司內(nèi)部研發(fā)的搜索引擎做支撐。搜索團(tuán)隊(duì)也是剛剛搭建,leader即是面試我的楊總,另外還有地主、老曹加我一共四個(gè)人。楊總是從亞馬遜剛挖來(lái)的搜索專家、另外兩個(gè)兄弟也是從其他團(tuán)隊(duì)調(diào)過(guò)來(lái)的工作5年以上的技術(shù)骨干, 能加入這樣的一個(gè)團(tuán)隊(duì)我在暗自慶幸的同時(shí)也不免也壓力重重,一個(gè)團(tuán)隊(duì)就我一個(gè)菜鳥 并且之前壓根沒(méi)聽(tīng)說(shuō)過(guò)搜索引擎這玩意!
有句話"讀萬(wàn)卷書不如行萬(wàn)里路,行萬(wàn)里路不如閱人無(wú)數(shù),閱人無(wú)數(shù)不如高手指路“,在職業(yè)發(fā)展上我個(gè)人一直認(rèn)為自己很幸運(yùn),經(jīng)歷的幾個(gè)公司都遇到一個(gè)相當(dāng)不錯(cuò)的老大,一個(gè)好的老大不僅會(huì)在技術(shù)上讓你少走很多彎路并且在思維和做事方式上會(huì)讓你職業(yè)生涯終身受益。在A公司是我技術(shù)成長(zhǎng)最快的一段時(shí)光,大方向和思維上有楊總親自指導(dǎo),程序和工程上兩位經(jīng)驗(yàn)豐富的老大哥經(jīng)常手把手不厭其煩的指導(dǎo)。相反大部分入行做搜索的可能沒(méi)我這么幸運(yùn),經(jīng)常對(duì)搜索最基本的分詞、倒排、相似度模型這些很核心的地方只會(huì)稀里糊涂的用,也許一兩行核心代碼就搞定的事情結(jié)果出了問(wèn)題根本束手無(wú)策。社區(qū)里太多這樣的問(wèn)題,而我詢問(wèn)提問(wèn)者的時(shí)候大部分屬于一個(gè)人單槍匹馬就踏進(jìn)搜索來(lái)了(上面leader根本不懂),或者沒(méi)時(shí)間(浮躁懶惰)細(xì)看最基本的知識(shí)點(diǎn),這一道門檻沒(méi)過(guò)去大部分人可能就對(duì)搜索失去信心,認(rèn)為不太好玩而離開(除非項(xiàng)目必須用),如此種種深感惋惜。
二、干貨篇 由于楊總本身就是搜索的專家,所以結(jié)合當(dāng)時(shí)業(yè)務(wù)特點(diǎn)在技術(shù)選型上團(tuán)隊(duì)很快就敲定 solr、lucene體系作為引擎內(nèi)核,記得當(dāng)時(shí)版本solr是1.4,lucene是2.9。要做的事情就是將第三方的銀杏搜索干掉替換成自己公司的搜索引擎并同時(shí)實(shí)現(xiàn)一些當(dāng)時(shí)無(wú)法支持的功能比如多維切面搜索,競(jìng)價(jià)搜索 同時(shí)也要對(duì)搜索排序效果有所改善。互聯(lián)網(wǎng)的天氣風(fēng)云變幻莫測(cè),由于A公司已經(jīng)仙逝,具體需求我只能找一個(gè)demo給大家細(xì)講。
上圖基本上是當(dāng)時(shí)搜索原始需求的一個(gè)原型,涵蓋了大部分垂直搜索的常用功能點(diǎn)。
1.搜索結(jié)果數(shù):表示搜索一個(gè)關(guān)鍵詞后相關(guān)的餐廳數(shù)量,這個(gè)不僅僅用來(lái)展示也是后臺(tái)計(jì)算分頁(yè)的一個(gè)重要數(shù)據(jù)。
2.過(guò)濾篩選項(xiàng):基本上就是餐廳服務(wù)和設(shè)施的一些篩選條件,有些是單選有些是多選。
3.維度切面搜索:這塊是大家比較熟悉的,大部分電商網(wǎng)站都會(huì)有這個(gè)功能區(qū),這個(gè)會(huì)讓用戶更快捷的通過(guò)幾種維度篩選結(jié)果,里面有些還會(huì)包含復(fù)雜的樹狀下鉆功能。這塊在solr里面是facet做支撐的,當(dāng)然前面的樹狀數(shù)據(jù)需要自己組織。
4.排序:搜索核心業(yè)務(wù)之一,一般默認(rèn)就是相關(guān)度(當(dāng)然這個(gè)大部分會(huì)加入業(yè)務(wù)因素和相關(guān)度一塊排序),餐廳的會(huì)有評(píng)分,熱銷等等排序。
5.結(jié)果展示:這塊主要展示搜索餐廳的具體信息,比如:名稱、地址、評(píng)分、銷量等等。
6.參與搜索的字段:這塊是隱含的一個(gè)需求,在選擇上也講究頗多,如果選多了會(huì)召回好多不相關(guān)的結(jié)果導(dǎo)致排序結(jié)果很糟,選少了可能查全率又不夠甚至出現(xiàn)東西本身就存在,而死活搜不出來(lái)的尷尬。 當(dāng)時(shí)的選擇是根據(jù)業(yè)務(wù)提的需求加上搜索數(shù)據(jù)統(tǒng)計(jì)分析(原來(lái)第三方的銀杏搜索)確定了 餐廳標(biāo)題,地址,地標(biāo),菜譜。
餐廳數(shù)量在60w左右的量級(jí),每天搜索次數(shù)在100w左右,期待搜索性能在平均響應(yīng)時(shí)間100ms以下(當(dāng)時(shí)第三方搜索引擎的平均響應(yīng)到了500ms)
。上圖是當(dāng)時(shí)的一個(gè)架構(gòu)圖,即便是現(xiàn)在來(lái)看對(duì)500w以下的數(shù)據(jù)量來(lái)說(shuō)仍然不失為一個(gè)很不錯(cuò)的架構(gòu)。當(dāng)然看似簡(jiǎn)單的一張圖,落地工作還是很繁雜的,下面我把主要模塊功能列舉一下以期給大家更方便的理解。
1.DB (餐廳信息的數(shù)據(jù)來(lái)源) 來(lái)自mysql和oracle(歷史原因?qū)е虏蛷d的不同信息是存在了不同類型的數(shù)據(jù)庫(kù)中,這樣在互聯(lián)網(wǎng)行業(yè)中見(jiàn)怪不怪)數(shù)據(jù)總共大概來(lái)源于20個(gè)表,初做搜索的朋友們可能感覺(jué)奇怪為什么要用這么多表,其實(shí)在搜索引擎中只要用到過(guò)濾、排序、切面搜索、檢索或者需要引擎返回的字段都需要采集到搜索引擎中。比如排序因素中的訂單量、口味評(píng)分、評(píng)論數(shù)量這些盡管在界面上看不到 但是要用于排序公式中所以也要一并采集進(jìn)來(lái),而這些顯然不會(huì)存在統(tǒng)一張表中,甚至有些數(shù)量需要程序做稍加計(jì)算才能得出。
2.dataCollector (數(shù)據(jù)采集系統(tǒng)) 負(fù)責(zé)將餐廳相關(guān)的變更數(shù)據(jù)近實(shí)時(shí)采集到searchDB中。技術(shù)細(xì)節(jié)采用了很簡(jiǎn)單的triger方式,將變更的信息triger到一個(gè)chang_list_in的表中,并給每條數(shù)據(jù)打上增刪改的標(biāo)記,datacollector的系統(tǒng)起來(lái)后會(huì)定期掃描此表并將最新的數(shù)據(jù)采集更新到searchDB中。
3. searchDB (搜索專用數(shù)據(jù)庫(kù)) 此庫(kù)中有兩個(gè)核心的表,一個(gè)是根據(jù)datacollector采集到的數(shù)據(jù)形成一個(gè)寬表big_res_table,可以理解成此表中的字段和solr配置中的schema是一致的。 另外一個(gè)核心表是change_list_out,此表由big_res_table triger觸發(fā)而來(lái),記錄了那些餐廳在big_res_table中進(jìn)行了更新,并同時(shí)加上增刪改的標(biāo)記,以備下一個(gè)系統(tǒng)IndexBuilder使用。
4.indexBuilder(full/delta)索引創(chuàng)建系統(tǒng)。 此系統(tǒng)負(fù)責(zé)將變更的餐廳寬表信息big_res_table中的數(shù)據(jù)組織成solr的要求格式發(fā)給solr創(chuàng)建索引。系統(tǒng)可以以全量(full)方式啟動(dòng)或者以增量(delta)方式啟動(dòng),全量方式啟動(dòng)則會(huì)將big_res_table中的數(shù)據(jù)全部往solr中發(fā)送一遍。增量方式啟動(dòng)則會(huì)以一個(gè)后進(jìn)程方式監(jiān)控change_list_out表的變化,近實(shí)時(shí)的去拉取變更的big_res_table數(shù)據(jù)發(fā)送給solr。(其實(shí)后來(lái)才知道這種是偽全量索引,不僅會(huì)引發(fā)一些數(shù)據(jù)問(wèn)題,而且對(duì)索引和查詢都沒(méi)有起到全量的作用,后面的篇幅中我會(huì)逐一跟大家講解如何調(diào)整架構(gòu)去規(guī)避這些問(wèn)題)
5. 引擎內(nèi)核(solr主從服務(wù)) solr采用一主三從,讀寫分離的方式架構(gòu)(可以類比mysql的主從),indexbuilder將數(shù)據(jù)發(fā)給solr master創(chuàng)建索引,三個(gè)solr slave會(huì)定期從solr master拉取最新的索引數(shù)據(jù)。這里解釋說(shuō)明一下, solr是一個(gè)獨(dú)立的搜索應(yīng)用服務(wù)器可以提供標(biāo)準(zhǔn)的http接口,solr本身是基于lucene的,而lucene本身只是一個(gè)搜索內(nèi)核jar包(或者說(shuō)lib庫(kù))要想做成一個(gè)搜索服務(wù)則還需要好多東西要做。如果把lucene比喻成毛坯房,則solr就可以看成是精裝修并家電齊全可以拎包入住的公寓房,當(dāng)然如果要過(guò)的更舒適的話則要再做些軟硬裝修(這個(gè)隨著垂直搜索業(yè)務(wù)的逐漸復(fù)雜我們后面會(huì)講到)
6.LB(負(fù)載均衡) load balance這個(gè)模塊是用來(lái)做負(fù)載均衡,比如三個(gè)solr slave可能有一臺(tái)機(jī)器配置好,則在流量分配上可以多分一些。另外有那個(gè)solr slave暫時(shí)不可用則 lb也負(fù)責(zé)將其下線, 并通知前面的search service模塊不讓請(qǐng)求再打過(guò)來(lái)。 (其實(shí)現(xiàn)在來(lái)看這部分完全可以用nginx替換掉,或者直接使用solr自己帶的LB也可以)
7.search service(搜索服務(wù)) 搜索服務(wù)負(fù)責(zé)接受web的請(qǐng)求并將請(qǐng)求轉(zhuǎn)化成solr可以理解的復(fù)雜語(yǔ)法(為了web層調(diào)用的方面searchservice封裝了大量的solr語(yǔ)法和主業(yè)務(wù)解析,以http api的形式提供給web端),同時(shí)負(fù)責(zé)組織返回的數(shù)據(jù)(比如切面數(shù)據(jù)統(tǒng)計(jì),樹狀結(jié)構(gòu)),當(dāng)然后期這里也處理了競(jìng)價(jià)和自然搜索的排序邏輯。
8.web (頁(yè)面展示系統(tǒng)) 這塊就是前面需求中的頁(yè)面原型的動(dòng)態(tài)數(shù)據(jù)實(shí)現(xiàn),根據(jù)檢索到的結(jié)果將數(shù)據(jù)展現(xiàn)出來(lái),有些要求實(shí)時(shí)的數(shù)據(jù)則會(huì)從數(shù)據(jù)庫(kù)獲取其他地方再獲取一遍和搜索的數(shù)據(jù)組合一塊呈現(xiàn)給用戶。
9.monitor(監(jiān)控系統(tǒng)) 監(jiān)控系統(tǒng)當(dāng)時(shí)實(shí)現(xiàn)了兩個(gè)主要工作,一個(gè)是發(fā)現(xiàn)任何solr服務(wù)不可用則自動(dòng)發(fā)郵件通知搜索團(tuán)隊(duì)每個(gè)人,另一個(gè)則是將solr服務(wù)下線通知LB(當(dāng)時(shí)是以文件交互方式)并同時(shí)周期性檢測(cè)服務(wù)是否已經(jīng)恢復(fù),恢復(fù)的話則會(huì)自動(dòng)通知LB上線并發(fā)郵件通知搜索團(tuán)隊(duì)每個(gè)人。
來(lái)到A公司之前,我一直感覺(jué)架構(gòu)師就是寫多了代碼的猿或者根本就是個(gè)傳說(shuō),進(jìn)入搜索團(tuán)隊(duì)一個(gè)月才使我相信架構(gòu)師真的存在,將一個(gè)復(fù)雜的系統(tǒng)瞬間給你庖丁解牛到一個(gè)個(gè)模塊,并理清楚模各塊之間的各種交互和業(yè)務(wù)邏輯,這并不是寫上十年增刪改查就能水到渠成做到的事情。好的架構(gòu)師能使系統(tǒng)模塊之間更松散的耦合在一塊,并可以根據(jù)團(tuán)隊(duì)人數(shù)以及技術(shù)水平?jīng)Q定劃分模塊的粒度和多少,以使得整個(gè)團(tuán)隊(duì)人盡其才并且工作不強(qiáng)互相依賴,最后整個(gè)大系統(tǒng)就像堆積木般將每個(gè)模塊輕松的組裝在一起而不出差錯(cuò)。更好的架構(gòu)師則其中的多個(gè)模塊又可以被將來(lái)某個(gè)大型的系統(tǒng)重用!
好了,今天先和大家聊到這里,晚安。
---------------下篇預(yù)告---------------------
除了架構(gòu)圖中的模塊還會(huì)有哪些你想不到的工程存在?
高大上的架構(gòu)背后又有多少臟活累活?
一個(gè)詞庫(kù)的整理又會(huì)遇到什么逗比奇葩的事件?
分詞和倒排在搜索引擎中到底承擔(dān)了什么角色?
------------------------------------------------
以上疑問(wèn)將在下篇中逐一揭密,敬請(qǐng)期待!
喜歡的朋友請(qǐng)掃描下方二維碼關(guān)注公眾號(hào):金沙數(shù)據(jù) 您將會(huì)及時(shí)得到最新的文章。
http://weixin.qq.com/r/tDpqctPEN45IrZcR92_m (二維碼自動(dòng)識(shí)別)
關(guān)鍵詞:數(shù)據(jù),索引,金沙,大話