當前位置: 妍妍網 > 碼農

低成本、高效能:滴滴Elasticsearch全業務套用與實踐

2024-06-26碼農

一、滴滴 Elasticsearch 簡介

1.簡介

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

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

2.架構

滴滴 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 介面。

3.使用者控制台

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

  • 套用管理: 允許業務方透過申請 AppID 來獲取讀寫索引的許可權。

  • 索引管理: 支持新建索引、申請索引讀寫許可權、索引 mapping 建立和更改、以及索引的清理和下線操作。

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

    同時業務方可以在查詢分析模組看到對應的異常分析和慢查分析等,方便查詢最佳化。監控方面業務方可以檢視索引元資訊(如文件數及大小等)以及讀寫速率等,以監控系統執行狀態。

    4.運維管控平台

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

  • 集群管控: 展示集群資訊,對使用者暴露的是邏輯集群,一個邏輯集群可包含多個物理集群,如使用者看到的集群資訊是一個 important 公共集群,但是真實的物理集群包含幾十個小的公共 important 集群

  • 租戶管理 (租戶元資訊和租戶級別的限流)

  • 模版管理: 索引樣版後設資料管理,非更新索引可以透過升版本調整 shard 數,也可以在此處對索引樣版限流

  • 異常分析: 模版分析、慢查分析及異常分析

  • 操作記錄 使用者行為及管控定時任務記錄

  • 二、Elasticsearch 在滴滴的套用

    1.業務場景

  • 線上全文檢索服務,如地圖 POI 起終點檢索

  • MySQL 即時數據快照,線上業務如訂單查詢

  • 一站式日誌檢索服務,透過 Kibana 查詢,如 trace 日誌

  • 時序數據分析,如安全數據監控

  • 簡單 OLAP 場景,如內部數據看板

  • 向量檢索,如客服 RAG

  • 2.部署模式

  • 物理機+小集群部署方式,最大集群機器規模100台物理機左右

  • 3.接入方式

  • 透過使用者控制台建立索引,業務方根據業務需求選擇對應集群

  • 透過閘道器查詢,根據集群等級提供 gateway vip 地址,該閘道器是一個 HTTP 型別的服務,我們做了相容,業務方可以透過官方提供的SDK讀寫Gateway,Gateway 會根據索引找到對應的ES集群

  • 4.數據同步方式

    一共兩種數據同步方式,一種是走同步中心(公司數據平台提供統一的同步服務),一種是透過 Gateway 即時寫入,同步中心支持即時類和離線類的數據同步方式。

    即時類:

  • 日誌 -> ES

  • MQ(Kafka、Pulsar)-> ES

  • MySQL -> ES

  • 即時類同步方式

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

    離線類:

  • Hive -> ES

  • 離線類Hive->ES

    Hive->ES 整體思路是透過 Batch Load,加快數據匯入。透過 MR 生成 Lucene 檔,之後透過封裝的 ES AppendLucene 外掛程式把 Lucene 檔寫入到 ES 中。Hive->ES 整體流程,如上圖所示:

  • 使用 MR 生成 Lucene 檔

  • Lucene 保存在 HDFS 裏

  • 將檔拉取到 DataNode 裏

  • 匯入到 ES 中

  • 三、引擎叠代

    1.精細化分級保障

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

  • 集群級別隔離: 4種保障級別(日誌集群、公共集群、獨立集群和雙活集群),業務接入時,會在使用者控制台選擇其想要的集群。如果選錯集群我們會透過 DCDR(下文介紹)幫助業務在不影響業務且不感知的前提下遷移到其他集群。

  • Clientnode 隔離: Clientnode 讀寫分離,當 Clientnode 異常時,能快速定位故障原因也能減少影響面。如集群寫入慢且寫入量過大,Clientnode 可能導致 OOM,此時只會影響寫入不會影響查詢,可以降低業務的影響面。

  • Datanode Region 隔離: 當集群出現異常索引(如異常索引導致整個 datanode 寫入過慢)時,可以透過打 label 的方式,讓異常索引快速遷移到指定機器,避免影響集群上其他業務。

  • 2.多活建設

    滴滴跨數據中心復制能力 - Didi Cross Datacenter Replication,由滴滴自研,簡稱DCDR,它能夠將數據從一個 Elasticsearch 集群原生復制到另一個 Elasticsearch 集群。原理如下圖所示,DCDR 工作在索引樣版或索引層面,采用主從索引設計模型,由 Leader 索引主動將數據 push 到 Follower 索引,從而保證了主從索引數據的強一致性。


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

  • Push-based 模型,即時寫入基於 Request

  • 新增 CheckPoint 避免全量數據拷貝

  • 新增 Sequence Number 保障更新操作主從一致性

  • 引入寫入佇列,避免大量數據復制導致 OOM

  • DCDR解決了數據跨集群或者跨機房的數據即時同步問題,且我們基於管控實作了雙活能力。

    ES DCDR 的詳細解析見:【 】

    3.效能專項: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 監控指標體系

  • ZGC監控指標體系

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

    ES JDK17的升級,詳情見:【 】

    4.成本最佳化

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

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

  • 索引 Mapping 最佳化,禁止部份欄位倒排、正排

  • 新增 ZSTD 壓縮演算法,CPU 降低15%

  • 接入大數據資產管理平台,梳理無用分區和索引,協助業務下線

  • 關於 ES 支持 ZSTD 的實作,詳情見:【 】

    5.多租戶資源隔離

    JDK原生執行緒池模型:

  • 主執行緒呼叫 execute、或者 submit 等方法送出任務給執行緒池。

  • 如果執行緒池中正在執行的工作執行緒數量小於 corePoolSize(核心執行緒數量),那麽馬上建立執行緒執行這個任務。

  • 如果執行緒池中正在執行的工作執行緒數量大於或等於 corePoolSize(核心執行緒數量),那麽將這個任務放入佇列,稍後執行。

  • 如果這時佇列滿了且正在執行的工作執行緒數量還小於 maximumPoolSize(最大執行緒數量),那麽會建立非核心工作執行緒立刻執行這個任務,這部份非核心工作執行緒空閑超過一定的時間(keepAliveTime)時,就會被銷毀回收。

  • 如果最終送出的任務超過了 maximumPoolSize(最大執行緒數量),那麽就會執行拒絕策略。

  • 我們借鑒了 Presto Resource Group 隔離的思路,策略是將原來的 search 執行緒池按照配置拆分為多個 seach 執行緒池並組建執行緒池組。由於多租戶的查詢 QPS、重要等級不同,可以配置相應的執行緒數量和佇列大小。透過執行緒池組模式,隔離不同 Appid 使用者的查詢請求。

    核心工作流程為獲取 Appid,根據配置的Appid隔離資訊將任務送出到對應的子執行緒組中執行。


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

    6.數據安全


    兩種級別的鑒權和認證:

  • Gateway 級別 主要是 Appid 級別的鑒權

  • ES 級別 (Clientnode、Datanode、MasterNode),主要是做認證

  • ES 的 X-Pack 外掛程式是有安全認證能力的,但是不支持集群捲動升級重新開機,無法快速回滾,誤刪儲存有穩定性風險,基於此我們自研了一個安全外掛程式,優勢:

  • 架構簡單,邏輯清晰,只需在 HTTP 請求處理環節中進行簡單的字串校驗,無需涉及節點內部 TCP 通訊驗證。

  • 支撐 ES 集群捲動重新開機升級

  • 支持一鍵開關安全認證能力,可以快速止損

  • 關於ES安全認證方案,詳情見:【 】

    7.穩定性治理

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


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

  • 事前預防為主,持續最佳化 我們每年都會把穩定性當做最重要的事情去做,規範先行,落實穩定性紅線,包括方案設計、程式碼規範、上線規範、報警處理及故障管理等。每年都會執行穩定性「踩地雷」專項,三年時間我們共解決了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 的機器學習能力,以便更好地為業務提供支持。

    作者丨杜若飛

    來源丨公眾號:滴滴技術(ID: didi_tech

    dbaplus社群歡迎廣大技術人員投稿,投稿信箱: [email protected]