天天看點

Elasticsearch 在滴滴的應用與實踐

作者:閃念基因

滴滴 Elasticsearch 簡介

簡介

Elasticsearch 是一個基于 Lucene 建構的開源、分布式、RESTful 接口的全文搜尋引擎,其每個字段均可被索引,且能夠橫向擴充至數以百計的伺服器存儲以及處理 TB 級的資料,其可以在極短的時間記憶體儲、搜尋和分析大量的資料。

滴滴 ES 發展至今,承接了公司絕大部分端上文字檢索、少部分日志場景和向量檢索場景,包括地圖 POI 檢索、訂單檢索、客服、内搜及把脈日志 ELK 場景等。滴滴 ES 在2020年由2.X更新到7.6.0,近幾年圍繞保穩定、控成本、提效能和優生态這幾個方向持續探索和改進,本文會圍繞這幾個方向展開介紹。

架構

Elasticsearch 在滴滴的應用與實踐

滴滴 ES 整體産品架構如上圖所示,目前ES服務基于實體機部署,Gateway 和管控基于容器部署,我們也調研過 ES on K8S,因為我們 ES 的業務場景多是線上端上文字檢索,考慮到穩定性,是以最後還是決定使用實體機部署模式。

管控層主要負責實作以下功能:智能 segment Merge(防止 segment 膨脹導緻 datanode Full GC),索引生命周期管理,索引預建立(避免每天淩晨索引集中建立,導緻 Master/Clientnode OOM),租戶管控等。

網關層(Gateway)除了負責讀寫轉發外,還具備查詢優化能力(例如,将 BKD 查詢改寫為數值類型的等值查詢或範圍查詢)、三級限流(包括 AppID、索引模闆級别和查詢 DSL 級别)、租戶鑒權功能以及 SQL 能力(基于 NLPChina 開源的 ES SQL 能力進行魔改并封裝到 Gateway)等。我們的檢索服務僅對外暴露 Gateway 接口。

使用者控制台

Elasticsearch 在滴滴的應用與實踐

使用者控制台是我們提供給業務方産品接入的平台,主要功能:

  • 應用管理:允許業務方通過申請 AppID 來擷取讀寫索引的權限。
  • 索引管理:支援建立索引、申請索引讀寫權限、索引 mapping 建立和更改、以及索引的清理和下線操作。

檢索查詢提供多種查詢方式,包括 Kibana、DSL 和 SQL,以滿足不同的查詢需求。

同時業務方可以在查詢分析子產品看到對應的異常分析和慢查分析等,友善查詢優化。監控方面業務方可以檢視索引元資訊(如文檔數及大小等)以及讀寫速率等,以監控系統運作狀态。

運維管控平台

Elasticsearch 在滴滴的應用與實踐

運維管控平台主要是滿足 RD 和 SRE 日常運維需求,主要功能包括以下幾個方面:

  • 叢集管控:展示叢集資訊,對使用者暴露的是邏輯叢集,一個邏輯叢集可包含多個實體叢集,如使用者看到的叢集資訊是一個 important 公共叢集,但是真實的實體叢集包含幾十個小的公共 important 叢集
  • 租戶管理(租戶元資訊和租戶級别的限流)
  • 模版管理:索引模闆中繼資料管理,非更新索引可以通過升版本調整 shard 數,也可以在此處對索引模闆限流
  • 異常分析:模版分析、慢查分析及異常分析
  • 操作記錄:使用者行為及管控定時任務記錄

Elasticsearch 在滴滴的應用

業務場景

  • 線上全文檢索服務,如地圖 POI 起終點檢索
  • MySQL 實時資料快照,線上業務如訂單查詢
  • 一站式日志檢索服務,通過 Kibana 查詢,如 trace 日志
  • 時序資料分析,如安全資料監控
  • 簡單 OLAP 場景,如内部資料看闆
  • 向量檢索,如客服 RAG

部署模式

  • 實體機+小叢集部署方式,最大叢集機器規模100台實體機左右

接入方式

  • 通過使用者控制台建立索引,業務方根據業務需求選擇對應叢集
  • 通過網關查詢,根據叢集等級提供 gateway vip 位址,該網關是一個 HTTP 類型的服務,我們做了相容,業務方可以通過官方提供的SDK讀寫Gateway,Gateway 會根據索引找到對應的ES叢集

資料同步方式

一共兩種資料同步方式,一種是走同步中心(公司資料平台提供統一的同步服務),一種是通過 Gateway 實時寫入,同步中心支援實時類和離線類的資料同步方式。

實時類:

  • 日志 -> ES
  • MQ(Kafka、Pulsar)-> ES
  • MySQL -> ES
Elasticsearch 在滴滴的應用與實踐

實時類同步方式

如上圖所示,實時類同步方式有2種,一種是日志和 MySQL Binlog 通過采集工具采集到 MQ,之後通過統一封裝的 DSINK 工具,通過 Flink 寫入到 ES;另一種是 MySQL 全量資料,其基于開源的 DataX 進行全量資料同步。

離線類:

  • Hive -> ES
Elasticsearch 在滴滴的應用與實踐

離線類Hive->ES

Hive->ES 整體思路是通過 Batch Load,加快資料導入。通過 MR 生成 Lucene 檔案,之後通過封裝的 ES AppendLucene 插件把 Lucene 檔案寫入到 ES 中。Hive->ES 整體流程,如上圖所示:

  1. 使用 MR 生成 Lucene 檔案
  2. Lucene 儲存在 HDFS 裡
  3. 将檔案拉取到 DataNode 裡
  4. 導入到 ES 中

引擎疊代

精細化分級保障

Elasticsearch 在滴滴的應用與實踐

精細化分級保障主要解決的問題是當叢集出現故障時,影響面降低到最低,主要包括以下政策:

  • 叢集級别隔離:4種保障級别(日志叢集、公共叢集、獨立叢集和雙活叢集),業務接入時,會在使用者控制台選擇其想要的叢集。如果選錯叢集我們會通過 DCDR(下文介紹)幫助業務在不影響業務且不感覺的前提下遷移到其他叢集。
  • Clientnode 隔離:Clientnode 讀寫分離,當 Clientnode 異常時,能快速定位故障原因也能減少影響面。如叢集寫入慢且寫入量過大,Clientnode 可能導緻 OOM,此時隻會影響寫入不會影響查詢,可以降低業務的影響面。
  • Datanode Region 隔離:當叢集出現異常索引(如異常索引導緻整個 datanode 寫入過慢)時,可以通過打 label 的方式,讓異常索引快速遷移到指定機器,避免影響叢集上其他業務。

多活建設

滴滴跨資料中心複制能力 - Didi Cross Datacenter Replication,由滴滴自研,簡稱DCDR,它能夠将資料從一個 Elasticsearch 叢集原生複制到另一個 Elasticsearch 叢集。原理如下圖所示,DCDR 工作在索引模闆或索引層面,采用主從索引設計模型,由 Leader 索引主動将資料 push 到 Follower 索引,進而保證了主從索引資料的強一緻性。

Elasticsearch 在滴滴的應用與實踐

我們調研了官方自帶的的 ES CCR,發現其收費且基于 pull-based 模型,時效性較差,是以我們的 DCDR 方案是:

  • Push-based 模型,實時寫入基于 Request
  • 新增 CheckPoint 避免全量資料拷貝
  • 新增 Sequence Number 保障更新操作主從一緻性
  • 引入寫入隊列,避免大量資料複制導緻 OOM

DCDR解決了資料跨叢集或者跨機房的資料實時同步問題,且我們基于管控實作了雙活能力。

ES DCDR 的詳細解析見:《探索ES高可用:滴滴自研跨資料中心複制技術詳解》

性能專項:JDK17 + ZGC

JDK11-G1 Yong GC 平均暫停時間長,不滿足業務 P99 要求,如 POI 逾時,時是180ms,P99 要求60ms内,支付業務 P99 500ms,訂單業務 P99 400ms;寫入資料量大的場景,GC 頻繁,加劇叢集寫入 reject 問題,寫入延時大,不滿足業務需求。

基于上述背景,我們對 JDK17-ZGC 進行調研,經過測試 ZGC 可以将 GC 暫停時間控制在10ms内,能夠很好地解決 GC 導緻的查詢耗時問題。同時針對日志這種高吞吐場景,測試了JDK17-G1,發現 GC 性能相較于 JDK11-G1 提升了15%,并且 JDK17 在向量化支援、字元串處理等方面做了許多優化,能在一定程度上緩解日志叢集的寫入壓力。是以我們決定将 ES JDK 版本從11更新到17,并将部分業務 GC 算法從 G1 更新到 ZGC,主要工作如下:

  • Groovy 文法更新、 Plugin 插件重構
  • 解決文法格式導緻代碼編譯失敗問題
  • 解決 ES 源碼觸發 JVM 編譯 BUG
  • 依賴 Jar 包更新、類替換、類重構、注解優化
  • 搭建 ZGC 監控名額體系
Elasticsearch 在滴滴的應用與實踐

ZGC監控名額體系

支付叢集上線ZGC後,P99從800ms降低到30ms,下降96%平均查詢耗時從25ms降低到6ms,下降75%。日志叢集更新JDK17後,寫入性能提升15~20%,解決寫入隊列堆積和 reject 問題。

ES JDK17的更新,詳情見:《解鎖滴滴ES的性能潛力:JDK 17和ZGC的更新之路》

成本優化

Elasticsearch 在滴滴的應用與實踐

成本優化主要包括降低機器成本和降低使用者成本。

降低機器成本核心是降低存儲規模和降低 CPU 使用率,即降低機器數;降低使用者成本的核心邏輯是降低業務用量,是以 ES 整體成本優化政策如下:

  • 索引 Mapping 優化,禁止部分字段倒排、正排
  • 新增 ZSTD 壓縮算法,CPU 降低15%
  • 接入大資料資産管理平台,梳理無用分區和索引,協助業務下線

關于 ES 支援 ZSTD 的實作,詳情見:《如何讓ES低成本、高性能?滴滴落地ZSTD壓縮算法的實踐分享》

多租戶資源隔離

JDK原生線程池模型:

  • 主線程調用 execute、或者 submit 等方法送出任務給線程池。
  • 如果線程池中正在運作的工作線程數量小于 corePoolSize(核心線程數量),那麼馬上建立線程運作這個任務。
  • 如果線程池中正在運作的工作線程數量大于或等于 corePoolSize(核心線程數量),那麼将這個任務放入隊列,稍後執行。
  • 如果這時隊列滿了且正在運作的工作線程數量還小于 maximumPoolSize(最大線程數量),那麼會建立非核心工作線程立刻運作這個任務,這部分非核心工作線程空閑超過一定的時間(keepAliveTime)時,就會被銷毀回收。
  • 如果最終送出的任務超過了 maximumPoolSize(最大線程數量),那麼就會執行拒絕政策。

我們借鑒了 Presto Resource Group 隔離的思路,政策是将原來的 search 線程池按照配置拆分為多個 seach 線程池并組建線程池組。由于多租戶的查詢 QPS、重要等級不同,可以配置相應的線程數量和隊列大小。通過線程池組模式,隔離不同 Appid 使用者的查詢請求。

Elasticsearch 在滴滴的應用與實踐

核心工作流程為擷取 Appid,根據配置的Appid隔離資訊将任務送出到對應的子線程組中運作。

Elasticsearch 在滴滴的應用與實踐

目前此優化主要用于一份索引資料會被很多個業務方使用的場景,如訂單業務,訂單業務會被公司各個業務線使用,是以查詢 appid 會非常多,我們通過多租戶資源隔離限制指定 Appid 的線程池大小,避免由于某業務突然發送大量讀請求導緻 CPU 打滿,核心業務受損。

資料安全

Elasticsearch 在滴滴的應用與實踐

兩種級别的鑒權和認證:

  • Gateway 級别:主要是 Appid 級别的鑒權
  • ES 級别(Clientnode、Datanode、MasterNode),主要是做認證

ES 的 X-Pack 插件是有安全認證能力的,但是不支援叢集滾動更新重新開機,無法快速復原,誤删存儲有穩定性風險,基于此我們自研了一個安全插件,優勢:

  • 架構簡單,邏輯清晰,隻需在 HTTP 請求處理環節中進行簡單的字元串校驗,無需涉及節點内部 TCP 通信驗證。
  • 支撐 ES 叢集滾動重新開機更新
  • 支援一鍵開關安全認證能力,可以快速止損

關于ES安全認證方案,詳情見:《資料安全加強:深入解析滴滴ES安全認證技術方案》

穩定性治理

線上文字檢索對穩定性要求非常高,是以過去的三年,我們穩定性方面主要做了如下圖所示的以下工作:

Elasticsearch 在滴滴的應用與實踐

穩定性治理主要是做好三件事:事前、事中和事後。事情預防為主,事中能夠快速定位和止損,事後注重複盤,避免問題重複出現,

  • 事前預防為主,持續優化:我們每年都會把穩定性當做最重要的事情去做,規範先行,落實穩定性紅線,包括方案設計、代碼規範、上線規範、報警處理及故障管理等。每年都會執行穩定性“掃雷”專項,三年時間我們共解決了61個穩定性隐患,如解決 Gateway Full GC 問題(業務限流後,Gateway會立馬恢複正常),中繼資料治理,重寫部分鎖解決 ThreadLocal 洩露(ThreadLocal 洩露會導緻部分節點突然 CPU 飙升)等,同時落地故障止損SOP
  • 監控報警體系建設,我們做了基礎監控(如硬碟、CPU等),名額監控(如shard數,master pending task 個數等),鍊路監控(監控 MQ Lag,提前發現鍊路延時問題)
  • 名額系統建設,通過 grafana 建設了監控大盤,包括模版名額,shard 名額,節點名額及叢集名額等,這些名額能夠協助我們快速定位故障原因,如 CPU 突增問題,我們可以做到5分鐘内快速止損
  • 止損側我們做了自愈系統(如磁盤故障,查詢突增),日常雙活切流演練,讀寫限流等,其中讀限流做了基于 Appid、索引模闆和查詢DSL的限流,當出現叢集 CPU 突增問題時,限流方案也會盡可能降低對業務的影響

總結與展望

近年來,我們基于 ES 7.6.0 版本,圍繞保穩定、控成本、提效能和優生态方面進行了持續的探索和改進。目前,我們的 ES 引擎已在滴滴内部統一應用于所有線上檢索場景,并在穩定性方面成為大資料架構部的标杆。

我們還嘗試過一些創新方案,如冷熱資料分離、離線上混合部署以及使用 Flink Checkpoint 機制替代 Translog 等,但由于性能或穩定性等方面的考慮,這些方案并未被采納。然而,随着技術的不斷發展,我們将繼續探索和完善這些方案,以應對未來可能出現的挑戰。

目前,我們使用的 ES 版本是 7.6,而社群的最新版本已經更新至 8.13,兩者之間存在約 4 年的版本差距。是以,我們今年的重點工作是将 ES 平滑更新至 8.13 版本,以解決以下問題:

  • 新版本的 ES Master 性能更優
  • 能夠根據負載自動平衡磁盤使用
  • 減少 segment 對記憶體的占用
  • 支援向量檢索的 ANN 等新特性

在性能方面,我們将針對更新場景優化寫入性能,同時改進查詢過程中的 Merge 政策。此外,我們還将持續探索新版本 ES 的機器學習能力,以便更好地為業務提供支援。

作者:杜若飛

來源-微信公衆号:滴滴技術

出處:https://mp.weixin.qq.com/s/nIYbtjzraQ9s-Lni24x42g