1. 程式人生 > >開源搜尋引擎排名第一,Elasticsearch是如何做到的?

開源搜尋引擎排名第一,Elasticsearch是如何做到的?

一、引言

 

隨著移動網際網路、物聯網、雲端計算等資訊科技蓬勃發展,資料量呈爆炸式增長。如今我們可以輕易得從海量資料裡找到想要的資訊,離不開搜尋引擎技術的幫助。

作為開源搜尋引擎領域排名第一的 Elasticsearch,能夠讓我們無需深入瞭解背後複雜的資訊檢索原理,就可實現基本的全文檢索功能,在資料量達到十億,百億規模仍然可以秒級返回檢索結果。

 

對於系統容災、資料安全性、可擴充套件性、可維護性等使用者關注的實際問題,在Elasticsearch 上也能得到有效解決。

 

二、Elasticsearch 介紹

 

Elasticsearch(ES)是一個基於 Lucene 構建的開源分散式搜尋分析引擎,可以近實時的索引、檢索資料。具備高可靠、易使用、社群活躍等特點,在全文檢索、日誌分析、監控分析等場景具有廣泛應用。

 

由於高可擴充套件性,叢集可擴充套件至百節點規模,處理PB級資料。通過簡單的 RESTful API 即可實現寫入、查詢、叢集管理等操作。

 

除了檢索,還提供豐富的統計分析功能。以及官方功能擴充套件包 XPack 滿足其他需求,如資料加密、告警、機器學習等。

 

另外,可通過自定義外掛,如 COS 備份、QQ 分詞等滿足特定功能需求。

 

1. Elasticsearch 架構與原理

 

 

基本概念 :

 

  • Cluster「叢集」:由部署在多個機器的ES節點組成,以處理較大資料集和實現高可用;

  • Node「節點」:機器上的ES程序,可配置不同型別的節點;

  • Master Node「主節點」:用於叢集選主。由其中一個節點擔任主節點,負責叢集元資料管理,如索引建立,節點離開加入叢集等;

  • Data Node「資料節點」:負責索引資料儲存;

  • Index「索引」:索引資料的邏輯集合,可類比關係型資料的DataBase;

  • Shard「分片」:索引資料子集,通過將分片分配至叢集不同節點,實現資料橫向擴充套件。以解決單個節點CPU、記憶體、磁碟處理能力不足的情況;

  • Primary Shard「主分片」:資料分片採用主從模式,由分片接收索引操作;

  • Replica Shard「副本分片」:主分片的拷貝,以提高查詢吞吐量和實現資料高可靠。主分片異常時,其中一個副本分片會自動提升為新的主分片。

 

為了便於大家理解ES裡的資料模型,將它與關係型資料庫 MySQL 做類比:

 

 

從上面架構圖可以看出,ES 架構非常簡潔。內建自動發現實現 Zen discovery,當一個節點啟動後,通過聯絡叢集成員列表即可加入叢集。

 

由其中一個節點擔任主節點,用於叢集元資料管理,維護分片在節點間的分配關係。當新節點加入集群后,Master 節點會自動遷移部分分片至新節點,均衡叢集負載。

 

 

分散式叢集難免有節點故障。主節點會定期探測叢集其他節點存活狀態,當節點故障後,會將節點移出叢集,並自動在其他節點上恢復故障節點上的分片。

 

主分片故障時會提升其中一個副本分片為主分片。其他節點也會探活主節點,當主節點故障後,會觸發內建的類 Raft 協議選主,並通過設定最少候選主節點數,避免叢集腦裂。

 

 

除了叢集管理,索引資料讀寫也是我們關心的重要部分。ES 採用 peer-to-peer 架構,每個節點儲存全量分片路由資訊,也就是每個節點均可以接收使用者讀寫。

 

如傳送寫入請求至節點 1,寫入請求預設通過文件 ID 的 Hash 值確定寫入到哪個主分片,這裡假設寫入到分片 0。

 

寫完主分片 P0,並行轉發寫入請求至副本分片 R0 所在節點,當副本分片所在節點確認寫入成功後返回客戶端報告寫入成功,保障資料安全性。並且寫入前,會確保 quorum 數量的副本數,避免網路分割槽導致寫入資料不一致。

 

 

查詢採用分散式搜尋,如請求發給節點3後,請求會轉發至索引的主分片或副本分片所在節點。

 

當然如果寫入、查詢均帶有路由欄位資訊。請求只會傳送給部分分片,避免全量分片掃描。這些節點完成查詢後將結果返回給請求節點,由請求節點匯聚各個節點的結果返回給客戶端。

 

 

2. Lucene原理

   

介紹完 ES 叢集基本原理,下面簡單介紹下ES的底層儲存引擎 Lucene。

 

首先 Lucene 是一款高效能的資訊檢索庫,提供索引和檢索基本功能。ES 在此基礎上解決可靠性、分散式叢集管理等問題最終形成產品化的全文檢索系統。


Lucene 解決的核心問題便是全文檢索。與傳統的檢索方式不同,全文檢索避免在查詢時進行全部內容掃描。

 

比如資料寫入後,首先會對寫入的文件欄位內容分詞,形成詞典表和與它關聯的倒排表。查詢時由關鍵詞分詞結果直接匹配詞典表內容,並獲取關聯的文件列表,快速獲取結果集。並通過排序規則,優先展示匹配度高的文件。

 

 

Lucene 為了加快索引速度,採用了 LSM Tree 結構,先把索引資料快取在記憶體。當記憶體空間佔用較高或到達一定時間後,記憶體中的資料會寫入磁碟形成一個數據段檔案(segment)。段檔案內包含詞典、倒排表、欄位資料等等多個檔案。

 

 

為了相容寫入效能和資料安全性,如避免記憶體緩衝區裡的資料因為機器故障丟失。ES 在寫記憶體的同時也會寫事物日誌 Translog。記憶體裡的資料會定期生成新的段檔案,寫入開銷更低的檔案系統快取即可開啟和讀取實現近實時搜尋。

 

 

三、Elasticsearch 應用場景

 

ES的典型使用場景有日誌分析、時序分析、全文檢索等。

 

1. 日誌實時分析場景

 

日誌是網際網路行業基礎廣泛的資料形式。典型日誌有用來定位業務問題的運營日誌,如慢日誌、異常日誌;用來分析使用者行為的業務日誌,如使用者的點選、訪問日誌;以及安全行為分析的審計日誌等。

 

Elastic 生態提供了完整的日誌解決方案。通過簡單部署,即可搭建一個完整的日誌實時分析服務。ES 生態完美的解決了日誌實時分析場景需求,這也是近幾年 ES 快速發展的一個重要原因。

 

日誌從產生到可訪問一般在 10s 級,相比於傳統大資料解決方案的幾十分鐘、小時級時效性非常高。

 

ES底層支援倒排索引、列儲存等資料結構,使得在日誌場景可以利用ES非常靈活的搜尋分析能力。通過ES互動式分析能力,即使在萬億級日誌的情況下,日誌搜尋響應時間也是秒級。

 

日誌處理的基本流程包含:日誌採集 -> 資料清洗 -> 儲存 -> 視覺化分析。Elastic Stack通過完整的日誌解決方案,幫助使用者完成對日誌處理全鏈路管理。

 

 

其中:

 

  • 日誌採集:通過輕量級日誌採集元件FileBeat實時讀取業務日誌檔案,傳送資料至下游元件如 Logstash。

  • 文字解析:利用正則解析等機制,將日誌文字資料轉換成結構化資料。可使用獨立的Logstash 服務或 Elasticsearch 內建的輕量級資料處理模組 Ingest Pipeline,完成資料清洗和轉換。

  • 資料儲存:通過 Elasticsearch 搜尋分析平臺進行資料持久儲存,提供全文搜尋和分析能力。

  • 視覺化分析:通過功能豐富的圖形介面,即可對日誌資料進行搜尋分析,如視覺化元件 Kibana。

 

 

2. 時序分析場景

 

時序資料是按時間順序記錄裝置、系統狀態變化的資料。典型的時序資料有傳統的伺服器監控指標資料、應用系統性能監控資料、智慧硬體、工業物聯網感測器資料等。

 

早在2017年我們也基於ES進行了時序分析場景的探索。時序分析場景具有高併發寫入、低查詢時延、多維分析的特點。

 

由於ES具有叢集擴充套件、批量寫入、讀寫帶路由、資料分片等能力,目前已實現線上單叢集最大規模達到 600+節點、1000w/s 的寫入吞吐、單條曲線或單個時間線的查詢延時可控制在 10ms。

 

ES提供靈活、多維度的統計分析能力,實現檢視監控按照地域、業務模組等靈活的進行統計分析。另外,ES支援列儲存、高壓縮比、副本數按需調整等能力,可實現較低儲存成本。最後時序資料也可通過Kibana元件輕鬆實現視覺化。

 

 

3. 搜尋服務場景

 

搜尋服務典型場景有像京東、拼多多、蘑菇街中的商品搜尋;應用商店中的應用APP搜尋;論壇、線上文件等站內搜尋。

 

這類場景使用者關注高效能、低延遲、高可靠、搜尋質量等。如單個服務最大需達到 10w+ QPS,請求平均響應時間在 20ms以內,查詢毛刺低於 100ms,高可用如搜尋場景通常要求 4 個 9 的可用性,支援單機房故障容災等。

 

目前雲上 Elasticsearch 服務已支援多可用區容災,故障分鐘級恢復能力。通過 ES 高效倒排索引,以及自定義打分、排序能力與豐富的分詞外掛,實現全文檢索需求。在開源全文檢索領域,ES 在 DB-Engines 搜尋引擎類別持續多年排名第一。

 

 

四、騰訊 Elasticserch 服務

   

騰訊內外部均有大量的日誌實時分析、時序資料分析、全文檢索需求場景。

 

目前我們已聯合 Elastic 公司在騰訊雲上提供了核心增強版 ES 雲服務,簡稱CES,其中核心增強包括 Xpack 商業套件和核心優化。

 

在服務公司內部以及公有云客戶過程中,也遇到了較多問題和挑戰,比如超大規模叢集,千萬級資料寫入,以及雲上使用者豐富的使用場景等。

 

下文將介紹我們在核心層面,從可用性,效能,成本等方面進行的優化措施。

 

1. 可用性優化

 

   

可用性 問題表現在三個方面:

 

(1)ES 核心系統健壯性不足 

 

這也是分散式系統共性難題。例如異常查詢、壓力過載叢集容易出現雪崩。叢集可擴充套件性不足,比如叢集分片數超10w會出現明顯的元資料管理瓶頸。以及叢集擴容、節點異常後加回叢集,存在節點、多硬碟之間資料不均問題。

 

(2)容災方案欠缺

 

需保障機房網路故障時可快速恢復服務,自然災害下防止資料丟失,誤操作後快速恢復資料等可靠性、資料安全性問題。

 

(3)系統缺陷

 

另外也包括在運營過程中發現的一些 ES 系統缺陷 ,比如說 Master 節點堵塞、分散式死鎖、滾動重啟緩慢等。

 

 

針對上面的問題,在系統健壯性方面,我們通過服務限流,容忍機器網路故障、異常查詢等導致的服務不穩定問題。

 

通過優化叢集元資料管理邏輯,提升叢集擴充套件能力一個數量級,支援千級節點叢集、百萬級分片數。叢集均衡方面,通過優化節點、多硬碟間的分片均衡,保證大規模叢集的壓力均衡。

 

容災方案 方面,我們通過擴充套件 ES 的外掛機制實現資料備份和回檔,可把 ES 的資料備份到 COS,保障資料安全性;通過管控系統建設支援跨可用區容災,使用者可以按需部署多個可用區,以容忍單機房故障。採用垃圾桶機制,保證使用者在欠費、誤操作等場景下,叢集資料可快速恢復。

 

系統缺陷方面,我們修復了滾動重啟、Master 阻塞、分散式死鎖等一系列 Bug。其中滾動重啟優化,可加速節點重啟速度 5+倍。Master 堵塞問題,我們在 ES 6.x 版本和官方一起做了優化。

 

2. 效能優化

 

效能問題,比如以日誌、監控為代表的時序場景,對寫入效能要求非常高,寫入併發可達 1000w/s。然而我們發現在帶主鍵寫入時,ES 效能會衰減 1+倍。

 

壓測場景下發現CPU 存在無法充分利用的情況。通常搜尋服務對查詢性要求非常高,一般要求 20w QPS, 平均響應時間小於 20ms,並且需儘量避免 GC、以及執行計劃不優等造成的查詢毛刺問題。

 

  

為了解決這些問題。寫入方面,針對主鍵去重場景,我們通過利用段檔案上記錄的最大最小值進行查詢裁剪,加速主鍵去重的過程,寫入效能提升 45%,具體可參考 Lucene-8980[1]。

 

對於壓測場景下 CPU 不能充分利用的問題,通過優化 ES 重新整理 Translog 時鎖粒度,避免資源搶佔,提升效能提升 20%,具體可參考ES-45765 /47790[2]。我們也正在嘗試通過向量化執行優化寫入效能,通過減少分支跳轉、指令 Miss,預期寫入效能可提升 1 倍。

 

查詢方面,我們通過優化段檔案合併策略,對於非活躍段檔案會自動觸發合併,收斂段檔案數以降低資源開銷,提升查詢效能。

 

根據每個段檔案上記錄的最大最小值進行查詢剪枝,提升查詢效能 40%。通過 CBO 策略,避免快取較大開銷的 Cache 操作導致產生 10+倍的查詢毛刺,具體可參考Lucene-9002[3]。

 

另外還包括優化 Composite 聚合中的效能問題,實現真正的翻頁操作,以及優化帶排序場景的聚合使得效能提升3-7倍。此外,我們也在嘗試通過一些新硬體來優化效能,比如說英特爾的 AEP、Optane、QAT 等。

 

3. 成本優化

 

 

成本方面主要體現在以日誌、監控為代表的時序場景對機器資源的消耗。結合線上典型的日誌、時序業務統計資料發現,硬碟、記憶體、計算資源的成本比例接近 8:4:1。

 

可以得出硬碟、記憶體是主要矛盾,其次是計算成本。而這類時序類場景有很明顯的訪問特性,也就是資料具有冷熱特性。

 

時序資料訪問具有近多遠少的特點,比如近 7 天資料的訪問量佔比可達到 95%以上,而歷史資料訪問較少,並且通常都是訪問統計類資訊。

 

 

硬碟成本方面,由於資料具有明顯的冷熱特性,我們採用冷熱分離架構,使用混合儲存的方案來平衡成本和效能。

 

由於歷史資料通常只是訪問統計資訊,我們採用預計算 Rollup 換取儲存和查詢效能,類似物化檢視。對於完全不使用歷史資料,也可以備份到更廉價的儲存系統如 COS。其他一些優化方式包括多盤策略相容資料吞吐與資料容災,以及通過生命週期管理等定期刪除過期資料等。

 

記憶體成本 方面,我們發現特別是大儲存機型,儲存資源才用了 20% 記憶體已不足。為了解決記憶體不足問題,我們採用 Off-Heap 技術,來提升堆內記憶體利用率,降低 GC 開銷,並且提升單個節點管理磁碟的能力。

 

將記憶體佔比較大的 FST 移到堆外管理,通過堆記憶體放堆外物件地址,避免堆內外資料拷貝。通過 Java 弱引用機制實現堆外物件記憶體回收,進一步提升記憶體使用率。

 

實現 32GB 堆內記憶體可管理 50 TB 左右磁碟空間,較原生版本有 10 倍提升,並且效能持平,而 GC 優勢提升明顯。


除了核心層面的優化,在平臺層通過管控平臺,支援雲上服務資源管理、例項例項管理等實現服務託管。方便快捷進行例項建立和規格調整。

 

通過運維支撐平臺中的監控系統、運維工具等保障服務質量。並通過正在建設的智慧診斷平臺發現服務潛在問題,實現了對內外部提供穩定可靠的 ES 服務。

 

 

騰訊內部,我們主導了 ES 產品開源協同,發現潛在問題,共同優化完善 ES,避免不同的團隊重複踩坑。

 

同時我們也將優秀的方案積極貢獻給社群,和官方及社群的 ES 愛好者們共同推動 ES 的發展。以騰訊 ES 核心研發為代表的團隊,截至目前我們共提交了 60 多個 PR,其中有 70% 被合併,公司內 ES 開源協同 PMC 成員共有 6 位 ES/Lucene 社群 contributor。

 

五、結語

 

 

Elasticsearch 在騰訊內外部廣泛應用於日誌實時分析、時序資料分析、全文檢索等場景。

 

目前單叢集規模達到千級節點、萬億級吞吐。通過核心增強版 ES 為大家提供高可靠,低成本,高效能的搜尋分析服務。後續我們仍需在可用性,效能和成本等方面持續優化 ES。

 

比如叢集可擴充套件性不足問題,通過優化叢集擴充套件性支援百萬級分片秒級建立 index。ES 的儲存成本問題,目前正在研發儲存與計算分離方案,進一步縮減成本,提升效能。以及存在使用和維護成本高的問題,後續通過多級分割槽、智慧診斷等提升ES的自動化和故障自愈能力,降低使用者使用和維護成本。

 

未來,也會近一步探索 ES 在多維分析領域的其他可能性。持續在大資料領域提供更有價值的搜尋分析服務。

 

參考資料:

[1] Lucene-8980:

https://github.com/apache/lucene-solr/pull/884

[2] ES-45765 /47790:

https://github.com/elastic/elasticsearch/pull/45765

[3] Lucene-9002:

https://github.com/apache/lucene-solr/pull/940

看騰訊技術,學雲端計算知識,就來雲+社群<