基於Elasticsearch搜索平臺設計

来源:http://www.cnblogs.com/tylercao/archive/2017/10/15/7672865.html
-Advertisement-
Play Games

背景 隨著公司業務的高速發展以及數據爆炸式的增長,當前公司各產線都有關於搜索方面的需求,但是以前的搜索服務系統由於架構與業務上的設計,不能很好的滿足各個業務線的期望,主要體現下麵三個問題: 1. 不能支持對語句級別的搜索,大量業務相關的屬性根本無法實現 2. 沒有任何搜索相關的指標評價體系 3. 擴 ...


背景

隨著公司業務的高速發展以及數據爆炸式的增長,當前公司各產線都有關於搜索方面的需求,但是以前的搜索服務系統由於架構與業務上的設計,不能很好的滿足各個業務線的期望,主要體現下麵三個問題:

  1. 不能支持對語句級別的搜索,大量業務相關的屬性根本無法實現
  2. 沒有任何搜索相關的指標評價體系
  3. 擴展性與維護性特別差

基於現狀,對行業內的搜索服務做出充分調研,確認使用ElasticSearch做底層索引存儲,同時重新設計現有搜索服務,使其滿足業務方對維護性、定製化搜索排序方面的需求。

整體技術架構

滬江搜索服務底層基於分散式搜索引擎ElasticSearch,ElasticSearch是一個基於Lucene構建的開源,分散式,Restful搜索引擎;能夠達到近實時搜索,穩定,可靠,快速響應的要求。

搜索服務整體分為5個子系統

  • 搜索服務(Search Server) : 提供搜索與查詢的功能
  • 更新服務(Index Server) : 提供增量更新與全量更新的功能
  • Admin 控制台 : 提供UI界面,方便索引相關的維護操作
  • ElasticSearch存儲系統 : 底層索引數據存儲服務
  • 監控平臺: 提供基於ELK日誌與zabbix的監控

外部系統介面設計

  • 查詢
    • 查詢介面提供http的調用方式,當出現跨機房訪問的時候,請使用http介面,其餘都可以使用dubbo RPC調用
  • 增量更新
    • 數據增量更新介面採用提供MQ的方式接入。當業務方出現數據更新的時候,只需將數據推送到對應的MQ通道中即可。更新服務會監聽每個業務方通道,及時將數據更新到ElasticSearch中
  • 全量索引
    • 更新服務會調用業務方提供的全量Http介面(該介面需提供分頁查詢等功能)

全量更新

眾所周知,全量更新的功能在搜索服務中是必不可少的一環。它主要能解決以下三個問題

  • 業務方本身系統的故障,出現大量數據的丟失
  • 業務高速發展產生增減欄位或者修改分詞演算法等相關的需求
  • 業務冷啟動會有一次性導入大批量數據的需求

基於上面提到的問題,我們與業務方合作實現了全量索引。但是在這個過程中,我們也發現一個通用的問題。在進行全量更新的時候,其實增量更新也在同時進行,如果這兩種更新同時在進行的話,就會有遇到少量增量更新的數據丟失。比如說下麵這個場景

  1. 業務方發現自己搜索業務alias_A數據大量數據丟失,所以進行索引重建。其中alias_A是別名,就是我們通常說alias,但是底層真正的索引是index_201701011200(建議:索引裡面包含時間屬性,這樣就能知道是什麼創建的)
  2. 首先創建一個新的索引index_201706011200,然後從數據中拉出數據並插入ES中,並記錄時間戳T1,最後索引完成的時間戳為T2,並切換搜索別名index_1指向index_201706011200。
  3. 索引創建成功之後的最新數據為T1這個時刻的,但是T1到T2這段時間的數據,並沒有獲取出來。同時index_201701011200老索引還在繼續消費MQ中的數據,包括T1到T2時間內的缺少數據。
  4. 所以每次索引重建的時候,都會缺少T1T2時間內的數據。

最後,針對上面這個場景,我們提出通過zookeeper分散式鎖來暫停index consumer的消費,具體步驟如下

  1. 創建new_index
  2. 獲取該index 對應的別名,來修改分散式鎖的狀態為stop
  3. index consumer監控stop狀態,暫停索引數據的更新
  4. new_index索引數據創建完畢,更新分散式鎖狀態為start
  5. index consumer監控start狀態,繼續索引數據的更新


這樣的話,我們就不用擔心在創建索引的這段時間內,數據會有缺少的問題。相信大家對於這種方式解決全量與增量更新數據有所體會。

集群無縫擴容

數據量爆炸式的增加,導致我們ES集群最終還是遇到了容量不足的問題。在此背景下,同時結合ES本身提供的無縫擴容功能,我們最終決定對線上ES集群進行了線上的無縫擴容,將從原來的3台機器擴容為5台,具體步驟如下

  • 擴容前準備
    • 目前我們線上已經有3台機器正在運行著,其中node1為master節點,node2和node3為data節點,節點通信採用單播的形式而非廣播的方式。
    • 準備2台(node4與node5)機器,其中機器本身配置與ES配置參數需保持一致
  • 擴容中增加節點
    • 啟動node4與node5(註意一個一個啟動),啟動完成之後,查看node1,2,3,4,5節點狀態,正常情況下node1,2,3節點都已發現node4與node5,並且各節點之間狀態應該是一致的
  • 重啟master node
    • 修改node1,2,3節點配置與node4,5保持一致,然後順序重啟node2與node3,一定要優先重啟data node,最後我們在重啟node1(master node).到此為止,我們的線上ES集群就線上無縫的擴容完畢

部署優化

  • 查詢與更新服務分離
    • 查詢服務與更新服務在部署上進行物理隔離,這樣可以隔離更新服務的不穩定對查詢服務的影響
  • 預留一半記憶體
    • ES底層存儲引擎是基於Lucene,Lucenede的倒排索引是先在記憶體中生成,然後定期以段的形式非同步刷新到磁碟上,同時操作系統也會把這些段文件緩存起來,以便更快的訪問。所以Lucene的性能取決於和OS的交互,如果你把所有的記憶體都分配給Elasticsearch,不留一點給Lucene,那你的全文檢索性能會很差的。所有官方建議,預留一半以上記憶體給Lucene使用
  • 記憶體不要超過32G
    • 跨32G的時候,會出現一些現象使得記憶體使用率還不如低於32G,具體原因請參考官方提供的這篇文章 Don’t Cross 32 GB!
  • 儘量避免使用wildcard
    • 其實使用wildcard查詢,有點類似於在資料庫中使用左右通配符查詢。(如:*foo*z這樣的形式)
  • 設置合理的刷新時間
    • ES中預設index.refresh_interval參數為1s。對於大多數搜索場景來說,數據生效時間不需要這麼及時,所以大家可以根據自己業務的容忍程度來調整

總結

本章主要介紹公司搜索服務的整體架構,重點對全量更新中數據一致性的問題,ES線上擴容做了一定的闡述,同時列舉了一些公司在部署ES上做的一些優化。本文主要目的,希望大家通過閱讀滬江搜索實踐,能夠給廣大讀者帶來一些關於搭建一套通用搜索的建議。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 使用 JPA 和 Hibernate 的好處之一是它提供了資料庫特定方言和功能抽象。 因此,理論上,您可以實現一個應用程式,將其連接到一個受支持的資料庫,並且它可以在不用更改任何代碼的情況下運行。Hibernate 真的很好。 但老實說,您沒有想過您的應用程式能與每個支持的資料庫完美運行,是嗎? ...
  • #include #include #include using namespace std; int main(){ double a,b,c; cout>a>>b>>c; if(a+b>c&&b+c>a&&c+a>b){ double s,area; s=(a+b+c)/2; area=sqrt... ...
  • 本節內容 - 通用可執行文件結構(COFF)(readelf -h) - COFF用段(section)存儲不同類型數據(readelf -S) - 常用段 - 演示:使用readelf、xxd、objdump、gdb查看可執行文件結構信息 - 演示:objcopy -add-section;st... ...
  • Given an array of n integers and q queries. Write a program to print floor value of mean in range l to r for each query in a new line. Input: The firs ...
  • #include #include using namespace std; //保留2位小數 int main(){ double x=123.456; double y=3.14159; double z=-3214.67; cout<<setiosflags(ios::fixed)<<seti... ...
  • Description:Java SE 9 is the latest update to the Java Platform(General Availability on 21 September 2017). This release includes much awaited new fea ...
  • 除了nodejs之外,後端技術(php/java等)及環境搭建一直都是大多數web前端開發人員的弱項,而且每當公司里進來一個新的前端開發人員,第一件事情要做的就是搭建開發環境,需要在新的電腦上安裝IDE、nodejs、npm以及團隊裡面需要用到的技術所需要的依賴,一般需要花費一兩天時間;另外,如果團 ...
  • 背景 公司業務由數以百計的分散式服務溝通,每一個請求路由過來後,會經過多個業務系統並留下足跡,並產生對各種緩存或者DB的訪問,但是這些分散的數據對於問題排查,或者流程優化比較有限。對於一個跨進程的場景,彙總收集並分析海量日誌就顯得尤為重要。在這種架構下,跨進程的業務流會經過很多個微服務的處理和傳遞, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...