今天和搜索部門一塊兒作了一下MQ的遷移,順便交流一下業務和技術。發現如今90後小夥都挺不錯。我是指能力和探究心。我家男孩,不招女婿。html
在前面的文章中也提到,咱們有媒資庫(樂視視頻音頻自己內容)和全網做品庫(外部視頻音頻內容),數據量級都在千萬級。咱們UV,PV,CV,VV都是保密的。因此做爲一個合格的員工來講………………數值我也不知道。總之,這些數據做爲最終數據源,要走一個跨多個部門的工做流才最終出如今用戶點擊搜索按鈕出現的搜索框裏。大致流程圖以下:java
這個流程圖之因此沒像以往同樣手繪,嗯,那是由於:鋼筆放在公司了。正則表達式
這裏面除了兩個庫都在咱們這邊以外,其餘的一個框是一個部門。咱們這邊給pipeline的數據交付使用的是我開發的離線服務。pipeline將各個來源的數據作重複歸併處理。就是一些視頻內容是同樣的,可是可能來源不一樣或者名稱有類似但可能不徹底相同,而其實是一個視頻。打個比方,大學時看過一個電影叫<a Cinderella story>翻譯成中文有的翻譯成《灰姑娘的故事》也有翻譯成《灰姑娘的玻璃手機》,可是能夠根據其導演和演員表等判斷實際上是同一個視頻。這些相同的視頻要聚合成一個專輯。推舉最優質的描述做爲專輯的描述。展開詳情有各個來源的排序後視頻列表。算法
正常全網搜索也會將自家的視頻放在前面:數據庫
這個歸併處理你們可能也猜到了,並行計算嘛,用的是mapreduce。由於是視頻數的組合操做,數量級是蠻大的。搜索引擎返回的是數據都是ID,真正的數據從詳情部門返回。加個代理是啥意思?對調用端透明嘛,有修改只要改代理端。apache
搜索引擎是獨立的部門,沒打過交道。可是我在上家公司的公司主要負責全公司的垂直搜索,數據來源都是關係型數據庫,數據量不大,當時用的是搜索引擎用的是solr。分詞器用的是開源的IK分詞器。由於當時公司作的是面向企業家的高端人脈,搜索對人名,公司名等的檢索結果的排序有不少特殊的要求,因此當時研究過度詞器的源碼,也對分詞器進行了一些更加切合項目的改造。好比有個需求是過濾輸入的html標籤。可是在Solr中對索引讀入後的第一個操做就是分詞,使用Solr自帶的或者外部的分詞器。而後再對分好的詞進行更細節的過濾或者近義詞之類的。可是這第一步就直接破壞了文檔的結構,變成了一個個單詞,而不是html文檔形式。再去除很麻煩並且效率低。因此我當時的作法是直接修改了IK分詞器的源碼,讀入數據第一個操做先過濾標籤。apache有現成的工具類。這樣避免了讀入讀出帶來的性能損耗。當時也作過測試,循環跑10w次用我改造後的分詞器和不改造分詞器用solr過濾器過濾正則表達式的方式比的話,執行效率大約高出20倍。當時的還發現不論是solr仍是ES,都是基於lucene的嘛,更適用於西文的一些檢索。像中文檢索不須要像西文那樣須要語言處理器變小寫而後再基於算法或匹配進行詞根化。反而須要更多基於詞典的,包括同義詞,近義詞這些。因此從分詞這方面也是有不少的優化空間的。編程
我的以爲作搜索數據分析很重要。好比從日誌分析中能夠發現有些用戶輸入搜索關鍵詞:賈躍亭,那麼他頗有可能對包含「樂視」關鍵詞的信息也頗有興趣。發現了這個問題以後,我就對這類數據作了一個詞庫,進行了搜索和索引上一些詞的雙向綁定。就是至關於一個同義詞的功能。建議將本文的題目放到幾個搜索引擎裏搜索一下,對比看看結果,挺有意思。緩存
詳情數據也是存在文檔型數據庫裏,其實用mongoDB挺合適的。可是公司有統一的cbase集羣,就直接放到cbase裏了。我常常須要跟人家解釋半天:cbase,couchbase,memcached都是啥關係。memcached你們都很熟悉。可是memcached不支持持久化。若是使用單純的memcached集羣,節點失效時沒有任何的容錯。應對措施須要交由用戶處理。因此就產生了一個增強版的memcached集羣:couchbase。數據層以memcached API對數據進行交互,系統在memcached程序中嵌入持久化引擎代碼對數據進行緩存,複製,持久化等操做,異步隊列的形式將數據同步到CouchDB中。因爲它實現了數據自動在多個節點本分,單節點失效不影響業務。支持自動分片,很容易在線維護集羣。cbase又是啥東西呢?這是我司對couchbase進行了一個二次開發,主要的改進點是對value的最大值進行了強行擴容:原本memcached最大Value設定是1M。咱們給擴容到4M。可是慎用大的value。value值從1K到不超過1M平均分佈時,實際使用容量不超過50%時性能較好。若是大value不少,達不到這個值性能就會急劇降低。安全
早在08年,09年的時候。facebook,mixi等國外知名互聯網公司爲了減小數據庫訪問次數,提升動態網頁的訪問速度,提升可擴展性,開始使用memcached。做爲以facebook爲標杆的人人網,這種技術也很快在其內部各個部門獲得了普及。由於memcached集羣採用的是服務器間互不通訊的分佈式方式。客戶端和服務器端的通訊採用的是分佈式算法。這就是所說的節點失效時沒有任何的容錯。服務器
這裏提一個概念,就是常見的容錯機制。我知道的,主要是6種。
☆ failover:失敗自動切換
當出現失敗,重試其餘服務器,一般用於讀操做,重試會帶來更長延遲。
像咱們的MQ客戶端配置,採用是failover爲roundrobin。採用輪詢調度算法來容錯。
☆ failfast:快速失敗
只發起一次調用,失敗當即報錯,一般用於非冪等性的寫操做。若是有機器正在重啓,可能會出現調用失敗。
咱們的一個數據庫雖然升級成了mariaDB。可是仍是一主多從。這時候寫入主庫失敗採用的就是failfast方式。
☆ failsafe:失敗安全
出現異常時,直接忽略,一般用於寫入日誌等操做。
☆ failback:失敗自動恢復
後臺記錄失敗請求,定時重發。一般用於消息通知操做。不可靠,重啓丟失。
☆ forking:並行調用多個服務器
只要一個成功即返回,一般用於實時性要求較高的讀操做。須要浪費更多服務資源。
☆ broadcast
廣播調用,全部提供逐個調用,任意一臺報錯則報錯。一般用於更新提供方本地狀態,速度慢,任意一臺報錯則報錯。
讀過《java併發編程實踐》的朋友看到容錯機制很容易會聯想到java的fail-fast和fail-safe。週五和90後小夥子交流技術也正好聊到集合類的相關問題。有一個問題是在AbstractList的迭代器中,set操做作了expectedModCount = modCount。按理說不須要改變長度,爲啥也要作這個操做。而實現它的子類set中都沒有實現這個操做。個人想法是有一些實現set的方法有多是經過添加刪除來變相實現的。總之,繼續於這個AbstractList的實現類都會檢查這個expectedModCount 和 modCount的一致性。不同會便可拋出併發修改異常,這就是failfast。而像CopyOnWriteArrayList這種的,寫操做是在複製的集合上進行修改,不會拋出併發修改異常是failsafe的。