實現一個自己的搜尋引擎的初始規劃

程式設計一生發表於2017-04-25

  在想自己和剛畢業的時候處理問題有什麼不同。剛畢業的時候如果想解除安裝停用什麼東西提示說正在使用,我就去找個強力解除安裝軟體。如果我想清理瀏覽器快取,會直接用工具,如果想找到快取路徑選擇性的清理,會百度一下這個瀏覽器的預設快取路徑在哪裡。現在,我會開啟資源監視器檢視磁碟活動,對檔案,找到使用檔案的程式;對應用,找到它在讀寫的檔案路徑。

  現在介面服務組的效能卡在memcahe快取上。對於快取的過渡依賴,而且為了維護這個快取資料,業務流程的複雜性大大提高。其實本身介面這塊業務流程是很簡單的,只是要求承擔很大的併發量。要高併發,業務就更得簡單。nginx服務單臺機器號稱能承載10億的併發,為啥?邏輯簡單啊,就是按照規則找到對應的處理服務,將請求轉發過去。

  前段時間接了個私活。話說這一年多的時間還真幹了不少事情,幹過私活創過業的。業務就是建立一個帶支付的途家+攜程。剛拿到活兒,因為是php的,我又不會php,愁死了。因為是男票幫忙接的活兒。我就說是男票把我給賣了。確實是,他接活兒,但是自己看都不看一眼,只負責拿錢。我自己啥都沒有,還怕做不好壞了男票的名聲。本來人家預算是2w的,我說這個得5w。最後給了3w。1個月時間確實是搞定了。總結一下,這個從UI設計到編碼測試只有我一個人的專案,就前端JS樣式這一樣,別人也很難做的很快。我之所以能做的很快,綜合能力是一方面,最重要的原因是:業務邏輯理的順,包括支付,結算,後臺給商家打款,統計分析。業務邏輯劃分的清楚,做起來工作量就沒有那麼大。話說男票給我接私活這事兒,我嘴裡是埋怨的,心裡很清楚:他之所以給我接這個活兒是因為我想做。他並不是為了錢,是真心知道我想要什麼。而我嘴上的埋怨也只是因為一時的辛苦發洩一下而已。這埋怨也是笑著埋怨的,誰也沒當回事情。在日本的時候看過一個日文版的韓國水木連續劇<黃真伊>,真伊有兩個愛她超過愛自己的母親。她的生母和老師。生母拼其一生想讓真伊得到愛,老師拼其一生想讓真伊得到痛。因為痛是才藝的源泉。恩浩註定不能和真伊在一起,因為他的軟弱。愛一個不對的人,心就像是浮萍,漂泊探索一無所獲。看破看不破,終究是寂寞。真伊與正翰的愛感化了所有人,而真伊終究也沒與正翰白首不相離。而愛一個對的人,他們的經歷是別人所不能比的,他們最終心裡都是踏實的。真伊為才藝而生,正翰為天下而活。這才是他們的平靜與歸宿。不像真伊那般有才,也不像真伊那般命苦。過著幸福的小生活,做著自己想做的事,吾復何求。

  又想到離線資料那個小專案,在想之前跑全量只是取ID都要跑四個小時,我寫的程式只要20多分鐘,為啥呢,最重要的原因也是劃分的清楚。人家問我這個專案用到了哪些執行緒之間共享資源的地方,我說:這裡面有個AtomicInteger作為執行緒計數器算不算,我需要計算是不是所有的執行緒都是正常跑完終止的。其他的共享資源我都放到一個類裡面了,但是Map我就是用的HashMap,也沒用到ConcurrentHashMap,話說我們也是知道併發包裡的各種併發容器的原理的。但是業務邏輯劃分清楚了,我能保證寫HashMap的時候,只有一個執行緒在訪問,我沒有必要非要用併發啊。所有的執行緒最終要生成全量檔案,我用幾百個執行緒,每個執行緒生成一個檔案,各自讀寫打包壓縮,各不干擾,當然要比給檔案加鎖,等待寫操作快得多。話說這個技巧也已經被用的很多了,lucene的新增索引就是這麼幹的。

  上週開會的時候,我突然想到(其實之前早就想到了,但是每次說都沒人搭理,就過去了),媒資介面高併發的地方都是根據各種條件取資料,其他的程式都是為了維護這份資料服務的,維護資料很複雜。除了接業務線的訊息,還有自己的資料庫和快取對比補資料的。將來,因為聯通和電信要做物理隔離,隔離後還需要一個寫快取的統一監控專門負責給業務線返回更新訊息,資料補償的。然而所有的這些複雜邏輯,一個搜尋引擎全能搞定。

  之所以我之前提議沒人搭理,分析其原因:我們目前的組內搜尋引擎做的不好,大家只會用最簡單的功能。而我並沒向大家完整介紹過搜尋引擎都能幹什麼,而且我自己什麼都沒有做。陽哥自己搭建了一套redis來做日誌的統一收集,我受到啟發。現在,我有伺服器,熟悉java底層和演算法,搭建一套適合中國人用的搜尋引擎又是我一直以來的心願,現在又有業務場景需要用,幹嘛不自己做一套。之前離開人人之後看過王志亮寫的庖丁jade的原始碼,覺得自己也是可以做這麼一套框架的,況且只是一個持久層框架,原理非常清晰明瞭。果然,來到樂視看到了和庖丁jade非常像的mango框架。如果現在我不研發這麼一套專門應用場景的,適合中文分詞的,非常合適作為列表快取的搜尋引擎框架出來,過兩年肯定會有人比我先發布的,因為確實是很有應用場景的。

  先說為什麼介面服務要用搜尋引擎。搜尋引擎可以支援高併發,之前用過基於lucene的solr搜尋引擎,可以支援單臺上萬的併發。它是有多少記憶體就可以吃掉多少記憶體的,將集中式快取的以空間換時間用到了極致。介面服務只更新快取,不更新DB。如果換做搜尋引擎,搜尋引擎每分鐘從資料庫的從庫中讀取資料,對資料庫基本沒壓力。業務線給我們發訊息,我更新完快取再返回訊息也需要好幾分鐘。用搜尋引擎實時性會更高。業務邏輯簡單,現在介面服務用到了龐大的SOA架構,邏輯複雜,響應時間長。用搜尋引擎,只需要一個介面服務呼叫搜尋引擎搞定所有事情。搜尋引擎內的資料高度結構化,可以新增複雜的條件,函式,分組,排序,實際上也是在JVM內完成的,直接和記憶體中資料互動。速度快太多了。介面服務目前的瓶頸在快取上(必須在快取上啊,整個都在和快取打交道),經常性的快取返回資料時間長。多個鍵值的時候mget效能差,還很容易堵塞,影響到整個服務。目前能採用的措施就是將一部分任務轉給DB,另外考慮將memcache換成Redis快取。不管是memcache還是redis,都不合適這種動輒就100K以上的大資料的情況。鍵值對的快取最佳應用場景都應該是key和value體積都是極小的。所以我們現在的嘗試其實都不解決本質問題。用的dubbo做的RPC呼叫也有問題,dubbo有自己的bug,一旦遇到就很頭大。增加這層dubbo,增加了通訊開銷和系統複雜性,實際性的好處卻沒得到發揮。而搜尋引擎本身就是為大資料而生,大資料量,大資料體,高併發,而且對於這種多維查詢,是搜尋引擎最合適的用武之地。搜尋引擎也可以單獨作為RPC的被呼叫方,直接給其他業務線用。我們甚至可以將介面服務接收請求介面層都去掉,介面服務只有一個搜尋引擎。德偉最頭疼的部署問題迎刃而解。

  最最重要的原因,搜尋引擎是基於全文索引的,目前的搜尋模型純波爾模型,向量空間模型,概率模型都是不適合像媒資這種主要是ID列表查詢的。相應的,搜尋引擎的分析工具的側重面也是不合適媒資這樣的業務場景的。

  來看介面服務目前的架構:

 

很複雜且不合理,需要很多的優化。其中還用到了Falcon監控平臺和美團點評的CAT監控。資料庫更新目前要通知ES搜尋引擎,通知快取,通知業務線。

  換用搜尋引擎之後的架構:

就是這麼簡單,要不是為了保持目前的對外介面不變,介面api都可以不要。

   搜尋引擎自己整合日誌,監控。想要除錯也只要輸入引數,內部處理過程可以一目瞭然。從實現上,包裝lucene做一個平臺即可。較其他搜尋引擎優化的點:著重提高根據ID維度作為查詢條件的有序輸出,將介面的常用操作函式化,使其適合作為介面服務。將solr中不合適中文分詞的詞根化等環節去掉,加強中文特有的拼音,近義詞的搜尋(等後續有時間時優化)。整合jvm,記憶體,cpu的日誌,監控和報警,部署方便。初始不需要做太多,以後根據業務場景需要慢慢優化。其實我是要嘗試使用自己的演算法的,自認才疏學淺,沒好意思說。

如需轉載,請註上我的原文連結: http://www.cnblogs.com/xiexj/p/6761570.html  謝謝哦~~

相關文章